Merge "Make class roots an image root" into dalvik-dev
diff --git a/src/class_linker.cc b/src/class_linker.cc
index d3a6ed0..1049107 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -563,15 +563,6 @@
   return oat_file;
 }
 
-struct ClassLinker::InitFromImageCallbackState {
-  ClassLinker* class_linker;
-
-  Class* class_roots[kClassRootsMax];
-
-  typedef std::tr1::unordered_map<std::string, ClassRoot> Table;
-  Table descriptor_to_class_root;
-};
-
 void ClassLinker::InitFromImage() {
   const Runtime* runtime = Runtime::Current();
   if (runtime->IsVerboseStartup()) {
@@ -614,23 +605,12 @@
   HeapBitmap* heap_bitmap = Heap::GetLiveBits();
   DCHECK(heap_bitmap != NULL);
 
-  InitFromImageCallbackState state;
-  state.class_linker = this;
-  for (size_t i = 0; i < kClassRootsMax; i++) {
-    ClassRoot class_root = static_cast<ClassRoot>(i);
-    state.descriptor_to_class_root[GetClassRootDescriptor(class_root)] = class_root;
-  }
-
   // reinit clases_ table
-  heap_bitmap->Walk(InitFromImageCallback, &state);
+  heap_bitmap->Walk(InitFromImageCallback, this);
 
   // reinit class_roots_
-  Class* object_array_class = state.class_roots[kObjectArrayClass];
-  class_roots_ = ObjectArray<Class>::Alloc(object_array_class, kClassRootsMax);
-  for (size_t i = 0; i < kClassRootsMax; i++) {
-    ClassRoot class_root = static_cast<ClassRoot>(i);
-    SetClassRoot(class_root, state.class_roots[class_root]);
-  }
+  Object* class_roots_object = spaces[0]->GetImageHeader().GetImageRoot(ImageHeader::kClassRoots);
+  class_roots_ = class_roots_object->AsObjectArray<Class>();
 
   // reinit array_interfaces_ from any array class instance, they should all be ==
   array_interfaces_ = GetClassRoot(kObjectArrayClass)->GetInterfaces();
@@ -660,10 +640,10 @@
 void ClassLinker::InitFromImageCallback(Object* obj, void* arg) {
   DCHECK(obj != NULL);
   DCHECK(arg != NULL);
-  InitFromImageCallbackState* state = reinterpret_cast<InitFromImageCallbackState*>(arg);
+  ClassLinker* class_linker = reinterpret_cast<ClassLinker*>(arg);
 
   if (obj->IsString()) {
-    state->class_linker->intern_table_->RegisterStrong(obj->AsString());
+    class_linker->intern_table_->RegisterStrong(obj->AsString());
     return;
   }
   if (!obj->IsClass()) {
@@ -680,15 +660,7 @@
 
   std::string descriptor = klass->GetDescriptor()->ToModifiedUtf8();
   // restore class to ClassLinker::classes_ table
-  state->class_linker->InsertClass(descriptor, klass);
-
-  // check if this is a root, if so, register it
-  typedef InitFromImageCallbackState::Table::const_iterator It;  // TODO: C++0x auto
-  It it = state->descriptor_to_class_root.find(descriptor);
-  if (it != state->descriptor_to_class_root.end()) {
-    ClassRoot class_root = it->second;
-    state->class_roots[class_root] = klass;
-  }
+  class_linker->InsertClass(descriptor, klass);
 }
 
 // Keep in sync with InitCallback. Anything we visit, we need to
@@ -964,8 +936,7 @@
     klass->SetDescriptor(intern_table_->InternStrong(descriptor));
   }
   uint32_t access_flags = dex_class_def.access_flags_;
-  // Make sure there aren't any "bonus" flags set, since we use them for runtime
-  // state.
+  // Make sure there aren't any "bonus" flags set, since we use them for runtime state.
   CHECK_EQ(access_flags & ~kAccClassFlagsMask, 0U);
   klass->SetAccessFlags(access_flags);
   klass->SetClassLoader(class_loader);
diff --git a/src/class_linker.h b/src/class_linker.h
index 747a6e4..7f08a9b 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -377,6 +377,11 @@
     class_roots_->Set(class_root, klass);
   }
 
+  ObjectArray<Class>* GetClassRoots() {
+    DCHECK(class_roots_ != NULL);
+    return class_roots_;
+  }
+
   static const char* class_roots_descriptors_[];
 
   const char* GetClassRootDescriptor(ClassRoot class_root) {
@@ -397,7 +402,7 @@
   friend class ObjectTest;
   FRIEND_TEST(ObjectTest, AllocObjectArray);
   FRIEND_TEST(ExceptionTest, FindExceptionHandler);
-  friend class ImageWriter;  // for GetDexCaches
+  friend class ImageWriter;  // for GetClassRoots
   DISALLOW_COPY_AND_ASSIGN(ClassLinker);
 };
 
diff --git a/src/image.h b/src/image.h
index 4a2efc5..a15ead7 100644
--- a/src/image.h
+++ b/src/image.h
@@ -71,6 +71,7 @@
     kCalleeSaveMethod,
     kOatLocation,
     kDexCaches,
+    kClassRoots,
     kImageRootsMax,
   };
 
diff --git a/src/image_writer.cc b/src/image_writer.cc
index 2b2ada4..f223136 100644
--- a/src/image_writer.cc
+++ b/src/image_writer.cc
@@ -147,6 +147,8 @@
                    String::AllocFromModifiedUtf8(oat_file_->GetLocation().c_str()));
   image_roots->Set(ImageHeader::kDexCaches,
                    dex_caches);
+  image_roots->Set(ImageHeader::kClassRoots,
+                   class_linker->GetClassRoots());
   for (int i = 0; i < ImageHeader::kImageRootsMax; i++) {
     CHECK(image_roots->Get(i) != NULL);
   }
diff --git a/src/oatdump.cc b/src/oatdump.cc
index e96b25c..3856f34 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -51,6 +51,7 @@
   "kCalleeSaveMethod",
   "kOatLocation",
   "kDexCaches",
+  "kClassRoots",
 };
 
 class OatDump {
@@ -73,8 +74,18 @@
     CHECK_EQ(arraysize(image_roots_descriptions_), size_t(ImageHeader::kImageRootsMax));
     for (int i = 0; i < ImageHeader::kImageRootsMax; i++) {
       ImageHeader::ImageRoot image_root = static_cast<ImageHeader::ImageRoot>(i);
-      os << StringPrintf("%s: %p\n",
-                         image_roots_descriptions_[i], image_header.GetImageRoot(image_root));
+      const char* image_root_description = image_roots_descriptions_[i];
+      Object* image_root_object = image_header.GetImageRoot(image_root);
+      os << StringPrintf("%s: %p\n", image_root_description, image_root_object);
+      if (image_root_object->IsObjectArray()) {
+        // TODO: replace down_cast with AsObjectArray (g++ currently has a problem with this)
+        ObjectArray<Object>* image_root_object_array
+            = down_cast<ObjectArray<Object>*>(image_root_object);
+        //  = image_root_object->AsObjectArray<Object>();
+        for (int i = 0; i < image_root_object_array->GetLength(); i++) {
+            os << StringPrintf("\t%d: %p\n", i, image_root_object_array->Get(i));
+        }
+      }
     }
     os << "\n";
 
diff --git a/src/object.h b/src/object.h
index 7634807..42235b8 100644
--- a/src/object.h
+++ b/src/object.h
@@ -248,16 +248,10 @@
   bool IsObjectArray() const;
 
   template<class T>
-  ObjectArray<T>* AsObjectArray() {
-    DCHECK(IsObjectArray());
-    return down_cast<ObjectArray<T>*>(this);
-  }
+  ObjectArray<T>* AsObjectArray();
 
   template<class T>
-  const ObjectArray<T>* AsObjectArray() const {
-    DCHECK(IsObjectArray());
-    return down_cast<const ObjectArray<T>*>(this);
-  }
+  const ObjectArray<T>* AsObjectArray() const;
 
   bool IsArrayInstance() const;
 
@@ -2106,6 +2100,18 @@
   return IsArrayInstance() && !GetClass()->GetComponentType()->IsPrimitive();
 }
 
+template<class T>
+inline ObjectArray<T>* Object::AsObjectArray() {
+  DCHECK(IsObjectArray());
+  return down_cast<ObjectArray<T>*>(this);
+}
+
+template<class T>
+inline const ObjectArray<T>* Object::AsObjectArray() const {
+  DCHECK(IsObjectArray());
+  return down_cast<const ObjectArray<T>*>(this);
+}
+
 inline bool Object::IsArrayInstance() const {
   return GetClass()->IsArrayClass();
 }
diff --git a/src/runtime.h b/src/runtime.h
index bd2c7a2..8252a60 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -191,7 +191,7 @@
   // The host prefix is used during cross compilation. It is removed
   // from the start of host paths such as:
   //    $ANDROID_PRODUCT_OUT/system/framework/core.oat
-  // to produce target paths such as 
+  // to produce target paths such as
   //    /system/framework/core.oat
   // Similarly it is prepended to target paths to arrive back at a
   // host past. In both cases this is necessary because image and oat