Get ClassLinker out of the business of allocating strings.

String is now the only place we allocate strings. This requires
a bit of finesse in order to make char[] available early during
bootstrap.

Change-Id: I494a2b0691b58fdafc96513c1e697a88d437c805
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 3e1eb06..09454d8 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -49,10 +49,12 @@
   Class* object_array_class = AllocClass(java_lang_Class);
   CHECK(object_array_class != NULL);
 
-  // string is necessary so that FindClass can assigning names to members
+  // string and char[] are necessary so that FindClass can assign names to members
   Class* java_lang_String = AllocClass(java_lang_Class);
   CHECK(java_lang_String != NULL);
   java_lang_String->object_size_ = sizeof(String);
+  Class* char_array_class = AllocClass(java_lang_Class);
+  CHECK(char_array_class != NULL);
 
   // create storage for root classes, save away our work so far
   class_roots_ = ObjectArray<Class>::Alloc(object_array_class, kClassRootsMax);
@@ -60,8 +62,12 @@
   class_roots_->Set(kJavaLangObject, java_lang_Object);
   class_roots_->Set(kObjectArrayClass, object_array_class);
   class_roots_->Set(kJavaLangString, java_lang_String);
+  class_roots_->Set(kCharArrayClass, char_array_class);
   // now that these are registered, we can use AllocClass() and AllocObjectArray
 
+  String::InitClasses(java_lang_String, char_array_class);
+  // Now AllocString* can be used
+
   // setup boot_class_path_ now that we can use AllocObjectArray to
   // DexCache instances
   for (size_t i = 0; i != boot_class_path.size(); ++i) {
@@ -127,8 +133,8 @@
   // now FindClass can be used for non-primitive array classes
 
   // run Object[] through FindClass to complete initialization
-  Class* Object_array_class = FindSystemClass("[Ljava/lang/Object;");
-  CHECK_EQ(object_array_class, Object_array_class);
+  Class* found_object_array_class = FindSystemClass("[Ljava/lang/Object;");
+  CHECK_EQ(object_array_class, found_object_array_class);
 
   // Setup the primitive type classes.
   class_roots_->Set(kPrimitiveByte, CreatePrimitiveClass("B"));
@@ -142,10 +148,9 @@
   class_roots_->Set(kPrimitiveVoid, CreatePrimitiveClass("V"));
   // now we can use FindSystemClass for anything, including for "[C"
 
-  Class* char_array = FindSystemClass("[C");
-  class_roots_->Set(kCharArrayClass, char_array);
-  String::InitClasses(java_lang_String, char_array);
-  // Now AllocString* can be used
+  // run char[] through FindClass to complete initialization
+  Class* found_char_array_class = FindSystemClass("[C");
+  CHECK_EQ(char_array_class, found_char_array_class);
 
   // ensure all class_roots_ were initialized
   for (size_t i = 0; i < kClassRootsMax; i++) {
@@ -201,14 +206,6 @@
                                               sizeof(Method)));
 }
 
-String* ClassLinker::AllocStringFromModifiedUtf8(int32_t utf16_length,
-                                                 const char* utf8_data_in) {
-  return String::AllocFromModifiedUtf8(class_roots_->Get(kJavaLangString),
-                                       class_roots_->Get(kCharArrayClass),
-                                       utf16_length,
-                                       utf8_data_in);
-}
-
 Class* ClassLinker::FindClass(const StringPiece& descriptor,
                               Object* class_loader,
                               const DexFile* dex_file) {
@@ -600,9 +597,14 @@
     // link step.
 
     Class* new_class = NULL;
-    if (!init_done_ && descriptor == "[Ljava/lang/Object;") {
+    if (!init_done_) {
+      if (descriptor == "[Ljava/lang/Object;") {
         new_class = class_roots_->Get(kObjectArrayClass);
         CHECK(new_class);
+      } else if (descriptor == "[C") {
+        new_class = class_roots_->Get(kCharArrayClass);
+        CHECK(new_class);
+      }
     }
     if (new_class == NULL) {
       new_class = AllocClass();
@@ -1546,7 +1548,7 @@
   const DexFile::StringId& string_id = dex_file->GetStringId(string_idx);
   int32_t utf16_length = dex_file->GetStringLength(string_id);
   const char* utf8_data = dex_file->GetStringData(string_id);
-  String* new_string = AllocStringFromModifiedUtf8(utf16_length, utf8_data);
+  String* new_string = String::AllocFromModifiedUtf8(utf16_length, utf8_data);
   // TODO: intern the new string
   referring->GetDexCache()->SetResolvedString(string_idx, new_string);
   return new_string;
diff --git a/src/class_linker.h b/src/class_linker.h
index 9f5df47..a4a9b2e 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -65,7 +65,6 @@
   StaticField* AllocStaticField();
   InstanceField* AllocInstanceField();
   Method* AllocMethod();
-  String* AllocStringFromModifiedUtf8(int32_t utf16_length, const char* utf8_data_in);
   template <class T>
   ObjectArray<T>* AllocObjectArray(size_t length) {
     return ObjectArray<T>::Alloc(class_roots_->Get(kObjectArrayClass), length);
diff --git a/src/object.h b/src/object.h
index 0063f58..7eede5d 100644
--- a/src/object.h
+++ b/src/object.h
@@ -1065,6 +1065,11 @@
                                  ascii_data_in);
   }
 
+  static String* AllocFromModifiedUtf8(int32_t utf16_length,
+                                       const char* utf8_data_in) {
+    return AllocFromModifiedUtf8(java_lang_String_, char_array_, utf16_length, utf8_data_in);
+  }
+
  public: // TODO: private
   // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
   CharArray* array_;
diff --git a/src/object_test.cc b/src/object_test.cc
index 46e9cca..d240d0c 100644
--- a/src/object_test.cc
+++ b/src/object_test.cc
@@ -27,7 +27,7 @@
       utf16_expected[i] = ch;
     }
 
-    String* string = class_linker_->AllocStringFromModifiedUtf8(length, utf8_in);
+    String* string = String::AllocFromModifiedUtf8(length, utf8_in);
     ASSERT_EQ(length,  static_cast<size_t>(string->count_));
     ASSERT_TRUE(string->array_ != NULL);
     ASSERT_TRUE(string->array_->GetChars() != NULL);