Interning image strings

Change-Id: I7e93b3975fe43d91d00b8185b65e8e0fd67ff6f4
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 570d797..a2e05c5 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -58,13 +58,13 @@
 
 ClassLinker* ClassLinker::Create(const std::vector<const DexFile*>& boot_class_path,
                                  const std::vector<const DexFile*>& class_path,
-                                 InternTable* intern_table, Space* space) {
+                                 InternTable* intern_table, bool image) {
   CHECK_NE(boot_class_path.size(), 0U);
   UniquePtr<ClassLinker> class_linker(new ClassLinker(intern_table));
-  if (space == NULL) {
-    class_linker->Init(boot_class_path, class_path);
+  if (image) {
+    class_linker->InitFromImage(boot_class_path, class_path);
   } else {
-    class_linker->Init(boot_class_path, class_path, space);
+    class_linker->Init(boot_class_path, class_path);
   }
   // TODO: check for failure during initialization
   return class_linker.release();
@@ -115,16 +115,11 @@
   java_lang_String->SetStatus(Class::kStatusResolved);
 
   // Backfill Class descriptors missing until this point
-  // TODO: intern these strings
-  java_lang_Class->SetDescriptor(
-      String::AllocFromModifiedUtf8("Ljava/lang/Class;"));
-  java_lang_Object->SetDescriptor(
-      String::AllocFromModifiedUtf8("Ljava/lang/Object;"));
-  object_array_class->SetDescriptor(
-      String::AllocFromModifiedUtf8("[Ljava/lang/Object;"));
-  java_lang_String->SetDescriptor(
-      String::AllocFromModifiedUtf8("Ljava/lang/String;"));
-  char_array_class->SetDescriptor(String::AllocFromModifiedUtf8("[C"));
+  java_lang_Class->SetDescriptor(intern_table_->InternStrong("Ljava/lang/Class;"));
+  java_lang_Object->SetDescriptor(intern_table_->InternStrong("Ljava/lang/Object;"));
+  object_array_class->SetDescriptor(intern_table_->InternStrong("[Ljava/lang/Object;"));
+  java_lang_String->SetDescriptor(intern_table_->InternStrong("Ljava/lang/String;"));
+  char_array_class->SetDescriptor(intern_table_->InternStrong("[C"));
 
   // Create storage for root classes, save away our work so far (requires
   // descriptors)
@@ -156,7 +151,7 @@
   // Create int array type for AllocDexCache (done in AppendToBootClassPath)
   Class* int_array_class = AllocClass(java_lang_Class, sizeof(Class));
   int_array_class->SetArrayRank(1);
-  int_array_class->SetDescriptor(String::AllocFromModifiedUtf8("[I"));
+  int_array_class->SetDescriptor(intern_table_->InternStrong("[I"));
   int_array_class->SetComponentType(GetClassRoot(kPrimitiveInt));
   IntArray::SetArrayClass(int_array_class);
   SetClassRoot(kIntArrayClass, int_array_class);
@@ -179,14 +174,15 @@
   // Field and Method are necessary so that FindClass can link members
   Class* java_lang_reflect_Field = AllocClass(java_lang_Class, sizeof(FieldClass));
   CHECK(java_lang_reflect_Field != NULL);
-  java_lang_reflect_Field->SetDescriptor(String::AllocFromModifiedUtf8("Ljava/lang/reflect/Field;"));
+  java_lang_reflect_Field->SetDescriptor(intern_table_->InternStrong("Ljava/lang/reflect/Field;"));
   java_lang_reflect_Field->SetObjectSize(sizeof(Field));
   SetClassRoot(kJavaLangReflectField, java_lang_reflect_Field);
   java_lang_reflect_Field->SetStatus(Class::kStatusResolved);
   Field::SetClass(java_lang_reflect_Field);
 
   Class* java_lang_reflect_Method = AllocClass(java_lang_Class, sizeof(MethodClass));
-  java_lang_reflect_Method->SetDescriptor(String::AllocFromModifiedUtf8("Ljava/lang/reflect/Method;"));
+  java_lang_reflect_Method->SetDescriptor(
+      intern_table_->InternStrong("Ljava/lang/reflect/Method;"));
   CHECK(java_lang_reflect_Method != NULL);
   java_lang_reflect_Method->SetObjectSize(sizeof(Method));
   SetClassRoot(kJavaLangReflectMethod, java_lang_reflect_Method);
@@ -358,7 +354,7 @@
   init_done_ = true;
 }
 
-struct ClassLinker::InitCallbackState {
+struct ClassLinker::InitFromImageCallbackState {
   ClassLinker* class_linker;
 
   Class* class_roots[kClassRootsMax];
@@ -370,15 +366,14 @@
   Set dex_caches;
 };
 
-void ClassLinker::Init(const std::vector<const DexFile*>& boot_class_path,
-                       const std::vector<const DexFile*>& class_path,
-                       Space* space) {
+void ClassLinker::InitFromImage(const std::vector<const DexFile*>& boot_class_path,
+                                const std::vector<const DexFile*>& class_path) {
   CHECK(!init_done_);
 
   HeapBitmap* heap_bitmap = Heap::GetLiveBits();
   DCHECK(heap_bitmap != NULL);
 
-  InitCallbackState state;
+  InitFromImageCallbackState state;
   state.class_linker = this;
   for (size_t i = 0; i < kClassRootsMax; i++) {
     ClassRoot class_root = static_cast<ClassRoot>(i);
@@ -386,7 +381,7 @@
   }
 
   // reinit clases_ table
-  heap_bitmap->Walk(InitCallback, &state);
+  heap_bitmap->Walk(InitFromImageCallback, &state);
 
   // reinit class_roots_
   Class* object_array_class = state.class_roots[kObjectArrayClass];
@@ -396,21 +391,13 @@
     SetClassRoot(class_root, state.class_roots[class_root]);
   }
 
-  // reinit intern table
-  // TODO: remove interned_array, make all strings in image interned (and remove space argument)
-  ObjectArray<Object>* interned_array = space->GetImageHeader().GetInternedArray();
-  for (int32_t i = 0; i < interned_array->GetLength(); i++) {
-    String* string = interned_array->Get(i)->AsString();
-    intern_table_->RegisterStrong(string);
-  }
-
   // reinit array_interfaces_ from any array class instance, they should all be ==
   array_interfaces_ = GetClassRoot(kObjectArrayClass)->GetInterfaces();
   DCHECK(array_interfaces_ == GetClassRoot(kBooleanArrayClass)->GetInterfaces());
 
   // build a map from location to DexCache to match up with DexFile::GetLocation
   std::tr1::unordered_map<std::string, DexCache*> location_to_dex_cache;
-  typedef InitCallbackState::Set::const_iterator It;  // TODO: C++0x auto
+  typedef InitFromImageCallbackState::Set::const_iterator It;  // TODO: C++0x auto
   for (It it = state.dex_caches.begin(), end = state.dex_caches.end(); it != end; ++it) {
     DexCache* dex_cache = *it;
     std::string location = dex_cache->GetLocation()->ToModifiedUtf8();
@@ -454,11 +441,15 @@
   FinishInit();
 }
 
-void ClassLinker::InitCallback(Object* obj, void *arg) {
+void ClassLinker::InitFromImageCallback(Object* obj, void *arg) {
   DCHECK(obj != NULL);
   DCHECK(arg != NULL);
-  InitCallbackState* state = reinterpret_cast<InitCallbackState*>(arg);
+  InitFromImageCallbackState* state = reinterpret_cast<InitFromImageCallbackState*>(arg);
 
+  if (obj->IsString()) {
+    state->class_linker->intern_table_->RegisterStrong(obj->AsString());
+    return;
+  }
   if (!obj->IsClass()) {
     return;
   }
@@ -484,7 +475,7 @@
   }
 
   // check if this is a root, if so, register it
-  typedef InitCallbackState::Table::const_iterator It;  // TODO: C++0x auto
+  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;
@@ -531,7 +522,7 @@
 
 DexCache* ClassLinker::AllocDexCache(const DexFile& dex_file) {
   DexCache* dex_cache = down_cast<DexCache*>(AllocObjectArray<Object>(DexCache::LengthAsArray()));
-  dex_cache->Init(String::AllocFromModifiedUtf8(dex_file.GetLocation().c_str()),
+  dex_cache->Init(intern_table_->InternStrong(dex_file.GetLocation().c_str()),
                   AllocObjectArray<String>(dex_file.NumStringIds()),
                   AllocObjectArray<Class>(dex_file.NumTypeIds()),
                   AllocObjectArray<Method>(dex_file.NumMethodIds()),
@@ -760,7 +751,7 @@
   if (klass->GetDescriptor() != NULL) {
     DCHECK(klass->GetDescriptor()->Equals(descriptor));
   } else {
-    klass->SetDescriptor(String::AllocFromModifiedUtf8(descriptor));
+    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
@@ -778,7 +769,7 @@
   size_t num_direct_methods = header.direct_methods_size_;
   size_t num_virtual_methods = header.virtual_methods_size_;
 
-  klass->SetSourceFile(String::AllocFromModifiedUtf8(dex_file.dexGetSourceFile(dex_class_def)));
+  klass->SetSourceFile(intern_table_->InternStrong(dex_file.dexGetSourceFile(dex_class_def)));
 
   // Load class interfaces.
   LoadInterfaces(dex_file, dex_class_def, klass);
@@ -885,12 +876,12 @@
   {
     int32_t utf16_length;
     std::string utf8(dex_file.CreateMethodDescriptor(method_id.proto_idx_, &utf16_length));
-    dst->SetSignature(String::AllocFromModifiedUtf8(utf16_length, utf8.c_str()));
+    dst->SetSignature(intern_table_->InternStrong(utf16_length, utf8.c_str()));
   }
   dst->SetProtoIdx(method_id.proto_idx_);
   dst->SetCodeItemOffset(src.code_off_);
   const char* shorty = dex_file.GetShorty(method_id.proto_idx_);
-  dst->SetShorty(String::AllocFromModifiedUtf8(shorty));
+  dst->SetShorty(intern_table_->InternStrong(shorty));
   dst->SetAccessFlags(src.access_flags_);
   dst->SetReturnTypeIdx(dex_file.GetProtoId(method_id.proto_idx_).return_type_idx_);
 
@@ -965,7 +956,7 @@
   Class* klass = AllocClass(sizeof(Class));
   CHECK(klass != NULL);
   klass->SetAccessFlags(kAccPublic | kAccFinal | kAccAbstract);
-  klass->SetDescriptor(String::AllocFromModifiedUtf8(descriptor));
+  klass->SetDescriptor(intern_table_->InternStrong(descriptor));
   klass->SetPrimitiveType(type);
   klass->SetStatus(Class::kStatusInitialized);
   bool success = InsertClass(descriptor, klass);
@@ -1078,7 +1069,7 @@
   if (new_class->GetDescriptor() != NULL) {
     DCHECK(new_class->GetDescriptor()->Equals(descriptor));
   } else {
-    new_class->SetDescriptor(String::AllocFromModifiedUtf8(descriptor.ToString().c_str()));
+    new_class->SetDescriptor(intern_table_->InternStrong(descriptor.ToString().c_str()));
   }
   Class* java_lang_Object = GetClassRoot(kJavaLangObject);
   new_class->SetSuperClass(java_lang_Object);