Setting klass_ fields of heap allocated objects

Change-Id: Ib1ab43254430497cce0660156394eebddd2cc445
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 15c2e40..19f2f93 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -27,12 +27,23 @@
 }
 
 void ClassLinker::Init() {
-  // Allocate and partially initialize the Object and Class classes.
+  // Allocate and partially initialize the Class, Object, Field, Method classes.
   // Initialization will be completed when the definitions are loaded.
-  java_lang_Object_ = Heap::AllocClass(NULL);
-  java_lang_Object_->descriptor_ = "Ljava/lang/Object;";
-  java_lang_Class_ = Heap::AllocClass(NULL);
+  java_lang_Class_ = reinterpret_cast<Class*>(Heap::AllocRaw(sizeof(Class), NULL));
   java_lang_Class_->descriptor_ = "Ljava/lang/Class;";
+  java_lang_Class_->object_size_ = sizeof(Class);
+  java_lang_Class_->klass_ = java_lang_Class_;
+
+  java_lang_Object_ = AllocClass(NULL);
+  java_lang_Object_->descriptor_ = "Ljava/lang/Object;";
+
+  java_lang_Class_->super_class_ = java_lang_Object_;
+
+  java_lang_ref_Field_ = AllocClass(NULL);
+  java_lang_ref_Field_->descriptor_ = "Ljava/lang/ref/Field;";
+
+  java_lang_ref_Method_ = AllocClass(NULL);
+  java_lang_ref_Method_->descriptor_ = "Ljava/lang/Method;";
 
   // Allocate and initialize the primitive type classes.
   primitive_byte_ = CreatePrimitiveClass(kTypeByte, "B");
@@ -44,6 +55,32 @@
   primitive_short_ = CreatePrimitiveClass(kTypeShort, "S");
   primitive_boolean_ = CreatePrimitiveClass(kTypeBoolean, "Z");
   primitive_void_ = CreatePrimitiveClass(kTypeVoid, "V");
+
+  char_array_class_ = AllocClass(NULL);
+  char_array_class_->descriptor_ = "[C";
+  char_array_class_->status_ = Class::kStatusInitialized;
+  char_array_class_->component_type_ = primitive_char_;
+  char_array_class_->array_rank_ = 1;
+  char_array_class_->primitive_type_ = Class::kPrimNot;
+  char_array_class_->super_class_ = java_lang_Object_;
+}
+
+Class* ClassLinker::AllocClass(DexFile* dex_file) {
+  Class* klass = reinterpret_cast<Class*>(Heap::AllocObject(java_lang_Class_));
+  klass->dex_file_ = dex_file;
+  return klass;
+}
+
+StaticField* ClassLinker::AllocStaticField() {
+  return reinterpret_cast<StaticField*>(Heap::AllocRaw(sizeof(StaticField), java_lang_ref_Field_));
+}
+
+InstanceField* ClassLinker::AllocInstanceField() {
+  return reinterpret_cast<InstanceField*>(Heap::AllocRaw(sizeof(InstanceField), java_lang_ref_Field_));
+}
+
+Method* ClassLinker::AllocMethod() {
+  return reinterpret_cast<Method*>(Heap::AllocRaw(sizeof(Method), java_lang_ref_Method_));
 }
 
 Class* ClassLinker::FindClass(const char* descriptor,
@@ -55,25 +92,52 @@
   Class* klass = LookupClass(descriptor, class_loader);
   if (klass == NULL) {
     // Class is not yet loaded.
+    const RawDexFile::ClassDef* class_def;
     if (dex_file == NULL) {
       // No .dex file specified, search the class path.
-      dex_file = FindInClassPath(descriptor);
-      if (dex_file == NULL) {
+      ClassPathEntry pair = FindInClassPath(descriptor);
+      if (pair.first == NULL) {
         LG << "Class " << descriptor << " really not found";
         return NULL;
       }
+      dex_file = pair.first;
+      class_def = pair.second;
+    } else {
+      class_def = dex_file->GetRaw()->FindClassDef(descriptor);
     }
     // Load the class from the dex file.
     if (!strcmp(descriptor, "Ljava/lang/Object;")) {
       klass = java_lang_Object_;
       klass->dex_file_ = dex_file;
+      klass->object_size_ = sizeof(Object);
+      if (class_def != NULL) {
+        char_array_class_->super_class_idx_ = class_def->class_idx_;
+      }
     } else if (!strcmp(descriptor, "Ljava/lang/Class;")) {
       klass = java_lang_Class_;
       klass->dex_file_ = dex_file;
+      klass->object_size_ = sizeof(Class);
+    } else if (!strcmp(descriptor, "Ljava/lang/ref/Field;")) {
+      klass = java_lang_ref_Field_;
+      klass->dex_file_ = dex_file;
+      klass->object_size_ = sizeof(Field);
+    } else if (!strcmp(descriptor, "Ljava/lang/ref/Method;")) {
+      klass = java_lang_ref_Method_;
+      klass->dex_file_ = dex_file;
+      klass->object_size_ = sizeof(Method);
+    } else if (!strcmp(descriptor, "Ljava/lang/String;")) {
+      klass = java_lang_String_;
+      klass->dex_file_ = dex_file;
+      klass->object_size_ = sizeof(String);
     } else {
-      klass = Heap::AllocClass(dex_file);
+      klass = AllocClass(dex_file);
     }
-    bool is_loaded = LoadClass(descriptor, klass);
+    bool is_loaded;
+    if (class_def == NULL) {
+      is_loaded = false;
+    } else {
+      is_loaded = LoadClass(*class_def, klass);
+    }
     if (!is_loaded) {
       // TODO: this occurs only when a dex file is provided.
       LG << "Class not found";  // TODO: NoClassDefFoundError
@@ -177,7 +241,7 @@
     for (size_t i = 0; i < klass->num_sfields_; ++i) {
       RawDexFile::Field raw_field;
       raw->dexReadClassDataField(&class_data, &raw_field, &last_idx);
-      StaticField* sfield = Heap::AllocStaticField();
+      StaticField* sfield = AllocStaticField();
       klass->sfields_[i] = sfield;
       LoadField(klass, raw_field, sfield);
     }
@@ -191,7 +255,7 @@
     for (size_t i = 0; i < klass->NumInstanceFields(); ++i) {
       RawDexFile::Field raw_field;
       raw->dexReadClassDataField(&class_data, &raw_field, &last_idx);
-      InstanceField* ifield = Heap::AllocInstanceField();
+      InstanceField* ifield = AllocInstanceField();
       klass->ifields_[i] = ifield;
       LoadField(klass, raw_field, ifield);
     }
@@ -205,7 +269,7 @@
     for (size_t i = 0; i < klass->NumDirectMethods(); ++i) {
       RawDexFile::Method raw_method;
       raw->dexReadClassDataMethod(&class_data, &raw_method, &last_idx);
-      Method* meth = Heap::AllocMethod();
+      Method* meth = AllocMethod();
       klass->direct_methods_[i] = meth;
       LoadMethod(klass, raw_method, meth);
       // TODO: register maps
@@ -220,14 +284,13 @@
     for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
       RawDexFile::Method raw_method;
       raw->dexReadClassDataMethod(&class_data, &raw_method, &last_idx);
-      Method* meth = Heap::AllocMethod();
+      Method* meth = AllocMethod();
       klass->virtual_methods_[i] = meth;
       LoadMethod(klass, raw_method, meth);
       // TODO: register maps
     }
   }
-
-  return klass;
+  return true;
 }
 
 void ClassLinker::LoadInterfaces(const RawDexFile::ClassDef& class_def,
@@ -283,14 +346,15 @@
   }
 }
 
-DexFile* ClassLinker::FindInClassPath(const char* descriptor) {
+ClassLinker::ClassPathEntry ClassLinker::FindInClassPath(const char* descriptor) {
   for (size_t i = 0; i != class_path_.size(); ++i) {
     DexFile* dex_file = class_path_[i];
-    if (dex_file->HasClass(descriptor)) {
-      return dex_file;
+    const RawDexFile::ClassDef* class_def = dex_file->GetRaw()->FindClassDef(descriptor);
+    if (class_def != NULL) {
+      return ClassPathEntry(dex_file, class_def);
     }
   }
-  return NULL;
+  return ClassPathEntry(NULL, NULL);
 }
 
 void ClassLinker::AppendToClassPath(DexFile* dex_file) {
@@ -298,9 +362,9 @@
 }
 
 Class* ClassLinker::CreatePrimitiveClass(JType type, const char* descriptor) {
-  Class* klass = Heap::AllocClass(NULL);
+  Class* klass = AllocClass(NULL);
   CHECK(klass != NULL);
-  klass->super_class_ = java_lang_Class_;
+  klass->super_class_ = NULL;
   klass->access_flags_ = kAccPublic | kAccFinal | kAccAbstract;
   klass->descriptor_ = descriptor;
   klass->status_ = Class::kStatusInitialized;
@@ -946,7 +1010,7 @@
     klass->vtable_count_ += miranda_count;
 
     for (int i = 0; i < miranda_count; i++) {
-      Method* meth = Heap::AllocMethod();
+      Method* meth = AllocMethod();
       memcpy(meth, miranda_list[i], sizeof(Method));
       meth->klass_ = klass;
       meth->access_flags_ |= kAccMiranda;
@@ -968,11 +1032,11 @@
 }
 
 bool ClassLinker::LinkInstanceFields(Class* klass) {
-  int fieldOffset;
+  int field_offset;
   if (klass->GetSuperClass() != NULL) {
-    fieldOffset = klass->GetSuperClass()->object_size_;
+    field_offset = klass->GetSuperClass()->object_size_;
   } else {
-    fieldOffset = OFFSETOF_MEMBER(DataObject, fields_);
+    field_offset = OFFSETOF_MEMBER(DataObject, fields_);
   }
   // Move references to the front.
   klass->num_reference_ifields_ = 0;
@@ -1000,22 +1064,22 @@
     if (c != '[' && c != 'L') {
       break;
     }
-    pField->SetOffset(fieldOffset);
-    fieldOffset += sizeof(uint32_t);
+    pField->SetOffset(field_offset);
+    field_offset += sizeof(uint32_t);
   }
 
   // Now we want to pack all of the double-wide fields together.  If
   // we're not aligned, though, we want to shuffle one 32-bit field
   // into place.  If we can't find one, we'll have to pad it.
-  if (i != klass->NumInstanceFields() && (fieldOffset & 0x04) != 0) {
+  if (i != klass->NumInstanceFields() && (field_offset & 0x04) != 0) {
     InstanceField* pField = klass->GetInstanceField(i);
     char c = pField->GetType();
 
     if (c != 'J' && c != 'D') {
       // The field that comes next is 32-bit, so just advance past it.
       assert(c != '[' && c != 'L');
-      pField->SetOffset(fieldOffset);
-      fieldOffset += sizeof(uint32_t);
+      pField->SetOffset(field_offset);
+      field_offset += sizeof(uint32_t);
       i++;
     } else {
       // Next field is 64-bit, so search for a 32-bit field we can
@@ -1028,22 +1092,22 @@
           klass->SetInstanceField(i, singleField);
           klass->SetInstanceField(j, pField);
           pField = singleField;
-          pField->SetOffset(fieldOffset);
-          fieldOffset += sizeof(uint32_t);
+          pField->SetOffset(field_offset);
+          field_offset += sizeof(uint32_t);
           found = true;
           i++;
           break;
         }
       }
       if (!found) {
-        fieldOffset += sizeof(uint32_t);
+        field_offset += sizeof(uint32_t);
       }
     }
   }
 
   // Alignment is good, shuffle any double-wide fields forward, and
   // finish assigning field offsets to all fields.
-  assert(i == klass->NumInstanceFields() || (fieldOffset & 0x04) == 0);
+  assert(i == klass->NumInstanceFields() || (field_offset & 0x04) == 0);
   for ( ; i < klass->NumInstanceFields(); i++) {
     InstanceField* pField = klass->GetInstanceField(i);
     char c = pField->GetType();
@@ -1063,10 +1127,10 @@
       // This is a double-wide field, leave it be.
     }
 
-    pField->SetOffset(fieldOffset);
-    fieldOffset += sizeof(uint32_t);
+    pField->SetOffset(field_offset);
+    field_offset += sizeof(uint32_t);
     if (c == 'J' || c == 'D')
-      fieldOffset += sizeof(uint32_t);
+      field_offset += sizeof(uint32_t);
   }
 
 #ifndef NDEBUG
@@ -1096,7 +1160,7 @@
   }
 #endif
 
-  klass->object_size_ = fieldOffset;
+  klass->object_size_ = field_offset;
   return true;
 }
 
@@ -1170,7 +1234,7 @@
   const RawDexFile* raw = referring->GetDexFile()->GetRaw();
   const RawDexFile::StringId& string_id = raw->GetStringId(string_idx);
   const char* string_data = raw->GetStringData(string_id);
-  String* new_string = Heap::AllocStringFromModifiedUtf8(string_data);
+  String* new_string = Heap::AllocStringFromModifiedUtf8(java_lang_String_, char_array_class_, string_data);
   // TODO: intern the new string
   referring->GetDexFile()->SetResolvedString(new_string, string_idx);
   return new_string;