Initialize primitive type classes during linker initialization.

Change-Id: Ib31da85afcc59c5d0a14346fb7f97043487fd662
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 3475bd1..e1e9bef 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -19,6 +19,25 @@
 
 namespace art {
 
+void ClassLinker::Init() {
+  // Allocate and partially initialize the class Class.  This object
+  // will complete its initialization when its definition is loaded.
+  java_lang_Class_ = Heap::AllocClass();
+  java_lang_Class_->super_class_ = java_lang_Class_;
+  java_lang_Class_->descriptor_ = "Ljava/lang/Class;";
+
+  // Allocate and initialize the primitive type classes.
+  primitive_byte_ = CreatePrimitiveClass(kTypeByte, "B");
+  primitive_char_ = CreatePrimitiveClass(kTypeChar, "C");
+  primitive_double_ = CreatePrimitiveClass(kTypeDouble, "D");
+  primitive_float_ = CreatePrimitiveClass(kTypeFloat, "F");
+  primitive_int_ = CreatePrimitiveClass(kTypeInt, "I");
+  primitive_long_ = CreatePrimitiveClass(kTypeLong, "J");
+  primitive_short_ = CreatePrimitiveClass(kTypeShort, "S");
+  primitive_boolean_ = CreatePrimitiveClass(kTypeBoolean, "Z");
+  primitive_void_ = CreatePrimitiveClass(kTypeVoid, "V");
+}
+
 Class* ClassLinker::FindClass(const char* descriptor,
                               Object* class_loader,
                               DexFile* dex_file) {
@@ -37,8 +56,13 @@
       }
     }
     // Load the class from the dex file.
-    klass = dex_file->LoadClass(descriptor);
-    if (klass == NULL) {
+    if (!strcmp(descriptor, "Ljava/lang/Class;")) {
+      klass = java_lang_Class_;
+    } else {
+      klass = Heap::AllocClass();
+    }
+    bool is_loaded = dex_file->LoadClass(descriptor, klass);
+    if (!is_loaded) {
       // TODO: this occurs only when a dex file is provided.
       LG << "Class not found";  // TODO: NoClassDefFoundError
       return NULL;
@@ -106,9 +130,49 @@
   class_path_.push_back(dex_file);
 }
 
+Class* ClassLinker::CreatePrimitiveClass(JType type, const char* descriptor) {
+  Class* klass = Heap::AllocClass();
+  CHECK(klass != NULL);
+  klass->super_class_ = java_lang_Class_;
+  klass->access_flags_ = kAccPublic | kAccFinal | kAccAbstract;
+  klass->descriptor_ = descriptor;
+  klass->status_ = Class::kStatusInitialized;
+  return klass;
+}
 
-Class* ClassLinker::FindPrimitiveClass(const char* descriptor) {
-  return NULL;  // TODO
+Class* ClassLinker::FindPrimitiveClass(JType type) {
+  switch (type) {
+    case kTypeByte:
+      CHECK(primitive_byte_ != NULL);
+      return primitive_byte_;
+    case kTypeChar:
+      CHECK(primitive_char_ != NULL);
+      return primitive_char_;
+    case kTypeDouble:
+      CHECK(primitive_double_ != NULL);
+      return primitive_double_;
+    case kTypeFloat:
+      CHECK(primitive_float_ != NULL);
+      return primitive_float_;
+    case kTypeInt:
+      CHECK(primitive_int_ != NULL);
+      return primitive_int_;
+    case kTypeLong:
+      CHECK(primitive_long_ != NULL);
+      return primitive_long_;
+    case kTypeShort:
+      CHECK(primitive_short_ != NULL);
+      return primitive_short_;
+    case kTypeBoolean:
+      CHECK(primitive_boolean_ != NULL);
+      return primitive_boolean_;
+    case kTypeVoid:
+      CHECK(primitive_void_ != NULL);
+      return primitive_void_;
+    default:
+      LOG(FATAL) << "Unknown primitive type " << static_cast<int>(type);
+  };
+  return NULL;  // Not reachable.
 }
 
 bool ClassLinker::InsertClass(Class* klass) {
@@ -445,9 +509,10 @@
   // TODO: store interfaces_idx in the Class object
   // TODO: move this outside of link interfaces
   if (klass->interface_count_ > 0) {
+    size_t length = klass->interface_count_ * sizeof(klass->interfaces_[0]);
     interfaces_idx.reset(new uint32_t[klass->interface_count_]);
-    memcpy(interfaces_idx.get(), klass->interfaces_, klass->interface_count_);
-    memset(klass->interfaces_, 0, klass->interface_count_);
+    memcpy(interfaces_idx.get(), klass->interfaces_, length);
+    memset(klass->interfaces_, 0xFF, length);
   }
   // Mark the class as loaded.
   klass->status_ = Class::kStatusLoaded;
@@ -517,7 +582,7 @@
       LG << "Too many methods on interface";  // TODO: VirtualMachineError
       return false;
     }
-    for (size_t i = 0; i < count; ++count) {
+    for (size_t i = 0; i < count; ++i) {
       klass->GetVirtualMethod(i)->method_index_ = i;
     }
   } else {
@@ -580,7 +645,7 @@
     if (actual_count < max_count) {
       Method** new_vtable = new Method*[actual_count];
       memcpy(new_vtable, klass->vtable_, actual_count * sizeof(Method*));
-      delete klass->vtable_;
+      delete[] klass->vtable_;
       klass->vtable_ = new_vtable;
       LG << "shrunk vtable: "
          << "was " << max_count << ", "
@@ -666,7 +731,7 @@
       int k;  // must be signed
       for (k = klass->vtable_count_ - 1; k >= 0; --k) {
         if (interface_method->HasSameNameAndPrototype(klass->vtable_[k])) {
-          if (klass->vtable_[k]->IsPublic()) {
+          if (!klass->vtable_[k]->IsPublic()) {
             LG << "Implementation not public";
             return false;
           }
@@ -916,7 +981,8 @@
   }
   const char* descriptor = dex_file->GetRaw()->dexStringByTypeIdx(class_idx);
   if (descriptor[0] != '\0' && descriptor[1] == '\0') {
-    resolved = FindPrimitiveClass(descriptor);
+    JType type = static_cast<JType>(descriptor[0]);
+    resolved = FindPrimitiveClass(type);
   } else {
     resolved = FindClass(descriptor, referrer->GetClassLoader(), NULL);
   }