Initialize ClassLinker from image

Change-Id: Ibaf47b4181f7c6603a8b37e2eba8fa6509c927ed
diff --git a/src/class_linker.h b/src/class_linker.h
index bc7a780..ad29383 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -14,6 +14,7 @@
 #include "object.h"
 #include "thread.h"
 #include "unordered_map.h"
+#include "unordered_set.h"
 
 #include "gtest/gtest.h"
 
@@ -21,11 +22,20 @@
 
 class ClassLinker {
  public:
-  // Initializes the class linker.
-  static ClassLinker* Create(const std::vector<DexFile*>& boot_class_path);
+  // Initializes the class linker using DexFile and an optional boot Space.
+  static ClassLinker* Create(const std::vector<DexFile*>& boot_class_path, Space* boot_space);
 
   ~ClassLinker() {
     delete classes_lock_;
+    String::ResetClass();
+    BooleanArray::ResetArrayClass();
+    ByteArray::ResetArrayClass();
+    CharArray::ResetArrayClass();
+    DoubleArray::ResetArrayClass();
+    FloatArray::ResetArrayClass();
+    IntArray::ResetArrayClass();
+    LongArray::ResetArrayClass();
+    ShortArray::ResetArrayClass();
   }
 
   // Finds a class by its descriptor name.
@@ -43,17 +53,31 @@
   bool EnsureInitialized(Class* c);
 
   void RegisterDexFile(const DexFile* dex_file);
+  void RegisterDexFile(const DexFile* dex_file, DexCache* dex_cache);
 
-  void VisitRoots(Heap::RootVistor* root_visitor, void* arg);
+  const InternTable& GetInternTable() {
+    return intern_table_;
+  }
+
+  void VisitRoots(Heap::RootVistor* root_visitor, void* arg) const;
 
  private:
   ClassLinker()
       : classes_lock_(Mutex::Create("ClassLinker::Lock")),
+        class_roots_(NULL),
         init_done_(false) {
   }
 
+  // Initialize class linker from DexFile instances.
   void Init(const std::vector<DexFile*>& boot_class_path_);
 
+  // Initialize class linker from pre-initialized space.
+  void Init(const std::vector<DexFile*>& boot_class_path_, Space* space);
+  static void InitCallback(Object *obj, void *arg);
+  struct InitCallbackState;
+
+  void FinishInit();
+
   bool InitializeClass(Class* klass);
 
   // For early bootstrapping by Init
@@ -63,12 +87,12 @@
   // values that are known to the ClassLinker such as
   // kObjectArrayClass and kJavaLangString etc.
   Class* AllocClass();
-  DexCache* AllocDexCache();
+  DexCache* AllocDexCache(const DexFile* dex_file);
   Field* AllocField();
   Method* AllocMethod();
   template <class T>
   ObjectArray<T>* AllocObjectArray(size_t length) {
-    return ObjectArray<T>::Alloc(class_roots_->Get(kObjectArrayClass), length);
+    return ObjectArray<T>::Alloc(GetClassRoot(kObjectArrayClass), length);
   }
   PathClassLoader* AllocPathClassLoader(std::vector<const DexFile*> dex_files);
 
@@ -81,7 +105,8 @@
 
   DexCache* FindDexCache(const DexFile* dex_file) const;
 
-  void AppendToBootClassPath(DexFile* dex_file);
+  void AppendToBootClassPath(const DexFile* dex_file);
+  void AppendToBootClassPath(const DexFile* dex_file, DexCache* dex_cache);
 
   void LoadClass(const DexFile& dex_file,
                  const DexFile::ClassDef& dex_class_def,
@@ -165,7 +190,8 @@
 
   InternTable intern_table_;
 
-  // indexes into class_roots_
+  // indexes into class_roots_.
+  // needs to be kept in sync with class_roots_descriptors_.
   enum ClassRoot {
     kJavaLangClass,
     kJavaLangObject,
@@ -198,11 +224,33 @@
   ObjectArray<Class>* class_roots_;
 
   Class* GetClassRoot(ClassRoot class_root) {
+    DCHECK(class_roots_ != NULL);
     Class* klass = class_roots_->Get(class_root);
     DCHECK(klass != NULL);
     return klass;
   }
 
+  void SetClassRoot(ClassRoot class_root, Class* klass) {
+    DCHECK(!init_done_);
+
+    DCHECK(klass != NULL);
+    DCHECK(klass->class_loader_ == NULL);
+    DCHECK(klass->descriptor_ != NULL);
+    DCHECK(klass->descriptor_->Equals(GetClassRootDescriptor(class_root)));
+
+    DCHECK(class_roots_ != NULL);
+    DCHECK(class_roots_->Get(class_root) == NULL);
+    class_roots_->Set(class_root, klass);
+  }
+
+  static const char* class_roots_descriptors_[kClassRootsMax];
+
+  const char* GetClassRootDescriptor(ClassRoot class_root) {
+    const char* descriptor = class_roots_descriptors_[class_root];
+    CHECK(descriptor != NULL);
+    return descriptor;
+  }
+
   ObjectArray<Class>* array_interfaces_;
   InterfaceEntry* array_iftable_;