First pass of compiler wrapping class

Change-Id: I343625310f69cc4de315af91b9cc72bb4da8f59b
diff --git a/src/class_linker.cc b/src/class_linker.cc
index c28fc65..f37df3f 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -49,7 +49,7 @@
   "[S",
 };
 
-ClassLinker* ClassLinker::Create(const std::vector<DexFile*>& boot_class_path, Space* space) {
+ClassLinker* ClassLinker::Create(const std::vector<const DexFile*>& boot_class_path, Space* space) {
   scoped_ptr<ClassLinker> class_linker(new ClassLinker);
   if (space == NULL) {
     class_linker->Init(boot_class_path);
@@ -60,8 +60,13 @@
   return class_linker.release();
 }
 
+ClassLinker::ClassLinker()
+    : classes_lock_(Mutex::Create("ClassLinker::Lock")),
+      class_roots_(NULL),
+      init_done_(false) {
+}
 
-void ClassLinker::Init(const std::vector<DexFile*>& boot_class_path) {
+void ClassLinker::Init(const std::vector<const DexFile*>& boot_class_path) {
   CHECK(!init_done_);
 
   // java_lang_Class comes first, its needed for AllocClass
@@ -128,7 +133,9 @@
   // setup boot_class_path_ now that we can use AllocObjectArray to
   // create DexCache instances
   for (size_t i = 0; i != boot_class_path.size(); ++i) {
-    AppendToBootClassPath(boot_class_path[i]);
+    const DexFile* dex_file = boot_class_path[i];
+    CHECK(dex_file != NULL);
+    AppendToBootClassPath(*dex_file);
   }
   // now we can use FindSystemClass, at least for non-arrays classes.
 
@@ -170,6 +177,7 @@
   CHECK(dalvik_system_PathClassLoader != NULL);
   CHECK_EQ(dalvik_system_PathClassLoader->object_size_, sizeof(PathClassLoader));
   SetClassRoot(kDalvikSystemPathClassLoader, dalvik_system_PathClassLoader);
+  PathClassLoader::SetClass(dalvik_system_PathClassLoader);
 
   // Setup a single, global copy of "interfaces" and "iftable" for
   // reuse across array classes
@@ -267,7 +275,7 @@
   Set dex_caches;
 };
 
-void ClassLinker::Init(const std::vector<DexFile*>& boot_class_path, Space* space) {
+void ClassLinker::Init(const std::vector<const DexFile*>& boot_class_path, Space* space) {
   CHECK(!init_done_);
 
   HeapBitmap* heap_bitmap = Heap::GetLiveBits();
@@ -313,9 +321,10 @@
 
   // reinit boot_class_path with DexFile arguments and found DexCaches
   for (size_t i = 0; i != boot_class_path.size(); ++i) {
-    DexFile* dex_file = boot_class_path[i];
+    const DexFile* dex_file = boot_class_path[i];
+    CHECK(dex_file != NULL);
     DexCache* dex_cache = location_to_dex_cache[dex_file->GetLocation()];
-    AppendToBootClassPath(dex_file, dex_cache);
+    AppendToBootClassPath(*dex_file, dex_cache);
   }
 
   String::SetClass(GetClassRoot(kJavaLangString));
@@ -327,6 +336,7 @@
   IntArray::SetArrayClass(GetClassRoot(kIntArrayClass));
   LongArray::SetArrayClass(GetClassRoot(kLongArrayClass));
   ShortArray::SetArrayClass(GetClassRoot(kShortArrayClass));
+  PathClassLoader::SetClass(GetClassRoot(kDalvikSystemPathClassLoader));
 
   FinishInit();
 }
@@ -388,13 +398,27 @@
   root_visitor(array_interfaces_, arg);
 }
 
-DexCache* ClassLinker::AllocDexCache(const DexFile* dex_file) {
+ClassLinker::~ClassLinker() {
+  delete classes_lock_;
+  String::ResetClass();
+  BooleanArray::ResetArrayClass();
+  ByteArray::ResetArrayClass();
+  CharArray::ResetArrayClass();
+  DoubleArray::ResetArrayClass();
+  FloatArray::ResetArrayClass();
+  IntArray::ResetArrayClass();
+  LongArray::ResetArrayClass();
+  ShortArray::ResetArrayClass();
+  PathClassLoader::ResetClass();
+}
+
+DexCache* ClassLinker::AllocDexCache(const DexFile& dex_file) {
   DexCache* dex_cache = down_cast<DexCache*>(AllocObjectArray<Object>(DexCache::kMax));
-  dex_cache->Init(String::AllocFromModifiedUtf8(dex_file->GetLocation().c_str()),
-                  AllocObjectArray<String>(dex_file->NumStringIds()),
-                  AllocObjectArray<Class>(dex_file->NumTypeIds()),
-                  AllocObjectArray<Method>(dex_file->NumMethodIds()),
-                  AllocObjectArray<Field>(dex_file->NumFieldIds()));
+  dex_cache->Init(String::AllocFromModifiedUtf8(dex_file.GetLocation().c_str()),
+                  AllocObjectArray<String>(dex_file.NumStringIds()),
+                  AllocObjectArray<Class>(dex_file.NumTypeIds()),
+                  AllocObjectArray<Method>(dex_file.NumMethodIds()),
+                  AllocObjectArray<Field>(dex_file.NumFieldIds()));
   return dex_cache;
 }
 
@@ -417,15 +441,8 @@
   return down_cast<Method*>(GetClassRoot(kJavaLangReflectMethod)->NewInstance());
 }
 
-// TODO: remove once we can use java.lang.Class.getSystemClassLoader
-PathClassLoader* ClassLinker::AllocPathClassLoader(std::vector<const DexFile*> dex_files) {
-  PathClassLoader* cl = down_cast<PathClassLoader*>(GetClassRoot(kDalvikSystemPathClassLoader)->NewInstance());
-  cl->SetClassPath(dex_files);
-  return cl;
-}
-
 Class* ClassLinker::FindClass(const StringPiece& descriptor,
-                              ClassLoader* class_loader) {
+                              const ClassLoader* class_loader) {
   // TODO: remove this contrived parent class loader check when we have a real ClassLoader.
   if (class_loader != NULL) {
     Class* klass = FindClass(descriptor, NULL);
@@ -445,7 +462,7 @@
     if (descriptor[0] == '[') {
       return CreateArrayClass(descriptor, class_loader);
     }
-    DexFile::ClassPath& class_path = ((class_loader != NULL) ? class_loader->GetClassPath() : boot_class_path_);
+    const DexFile::ClassPath& class_path = ((class_loader != NULL) ? class_loader->GetClassPath() : boot_class_path_);
     DexFile::ClassPathEntry pair = DexFile::FindInClassPath(descriptor, class_path);
     if (pair.second == NULL) {
       std::string name(PrintableString(descriptor));
@@ -455,7 +472,7 @@
     }
     const DexFile& dex_file = *pair.first;
     const DexFile::ClassDef& dex_class_def = *pair.second;
-    DexCache* dex_cache = FindDexCache(pair.first);
+    DexCache* dex_cache = FindDexCache(dex_file);
     // Load the class from the dex file.
     if (!init_done_) {
       // finish up init of hand crafted class_roots_
@@ -586,7 +603,7 @@
 void ClassLinker::LoadClass(const DexFile& dex_file,
                             const DexFile::ClassDef& dex_class_def,
                             Class* klass,
-                            ClassLoader* class_loader) {
+                            const ClassLoader* class_loader) {
   CHECK(klass != NULL);
   CHECK(klass->dex_cache_ != NULL);
   CHECK_EQ(Class::kStatusNotReady, klass->status_);
@@ -604,7 +621,7 @@
   klass->status_ = Class::kStatusIdx;
 
   klass->super_class_ = NULL;
-  klass->super_class_idx_ = dex_class_def.superclass_idx_;
+  klass->super_class_type_idx_ = dex_class_def.superclass_idx_;
 
   size_t num_static_fields = header.static_fields_size_;
   size_t num_instance_fields = header.instance_fields_size_;
@@ -684,11 +701,11 @@
   if (list != NULL) {
     DCHECK(klass->interfaces_ == NULL);
     klass->interfaces_ = AllocObjectArray<Class>(list->Size());
-    DCHECK(klass->interfaces_idx_ == NULL);
-    klass->interfaces_idx_ = new uint32_t[list->Size()];
+    DCHECK(klass->interfaces_type_idx_ == NULL);
+    klass->interfaces_type_idx_ = new uint32_t[list->Size()];
     for (size_t i = 0; i < list->Size(); ++i) {
       const DexFile::TypeItem& type_item = list->GetTypeItem(i);
-      klass->interfaces_idx_[i] = type_item.type_idx_;
+      klass->interfaces_type_idx_[i] = type_item.type_idx_;
     }
   }
 }
@@ -699,7 +716,7 @@
                             Field* dst) {
   const DexFile::FieldId& field_id = dex_file.GetFieldId(src.field_idx_);
   dst->declaring_class_ = klass;
-  dst->name_ = ResolveString(klass, field_id.name_idx_, dex_file);
+  dst->name_ = ResolveString(dex_file, field_id.name_idx_, klass->GetDexCache());
   dst->descriptor_.set(dex_file.dexStringByTypeIdx(field_id.type_idx_));
   // TODO: Assign dst->type_.
   dst->access_flags_ = src.access_flags_;
@@ -711,7 +728,7 @@
                              Method* dst) {
   const DexFile::MethodId& method_id = dex_file.GetMethodId(src.method_idx_);
   dst->declaring_class_ = klass;
-  dst->name_ = ResolveString(klass, method_id.name_idx_, dex_file);
+  dst->name_ = ResolveString(dex_file, method_id.name_idx_, klass->GetDexCache());
   {
     int32_t utf16_length;
     scoped_array<char> utf8(dex_file.CreateMethodDescriptor(method_id.proto_idx_,
@@ -724,7 +741,7 @@
   dst->access_flags_ = src.access_flags_;
 
   dst->dex_cache_strings_ = klass->dex_cache_->GetStrings();
-  dst->dex_cache_classes_ = klass->dex_cache_->GetClasses();
+  dst->dex_cache_types_ = klass->dex_cache_->GetTypes();
   dst->dex_cache_methods_ = klass->dex_cache_->GetMethods();
   dst->dex_cache_fields_ = klass->dex_cache_->GetFields();
 
@@ -745,27 +762,23 @@
   }
 }
 
-void ClassLinker::AppendToBootClassPath(const DexFile* dex_file) {
-  CHECK(dex_file != NULL);
+void ClassLinker::AppendToBootClassPath(const DexFile& dex_file) {
   AppendToBootClassPath(dex_file, AllocDexCache(dex_file));
 }
 
-void ClassLinker::AppendToBootClassPath(const DexFile* dex_file, DexCache* dex_cache) {
-  CHECK(dex_file != NULL);
+void ClassLinker::AppendToBootClassPath(const DexFile& dex_file, DexCache* dex_cache) {
   CHECK(dex_cache != NULL);
-  boot_class_path_.push_back(dex_file);
+  boot_class_path_.push_back(&dex_file);
   RegisterDexFile(dex_file, dex_cache);
 }
 
-void ClassLinker::RegisterDexFile(const DexFile* dex_file) {
-  CHECK(dex_file != NULL);
+void ClassLinker::RegisterDexFile(const DexFile& dex_file) {
   RegisterDexFile(dex_file, AllocDexCache(dex_file));
 }
 
-void ClassLinker::RegisterDexFile(const DexFile* dex_file, DexCache* dex_cache) {
-  CHECK(dex_file != NULL);
+void ClassLinker::RegisterDexFile(const DexFile& dex_file, DexCache* dex_cache) {
   CHECK(dex_cache != NULL);
-  dex_files_.push_back(dex_file);
+  dex_files_.push_back(&dex_file);
   dex_caches_.push_back(dex_cache);
 }
 
@@ -779,9 +792,9 @@
   return *dex_files_[-1];
 }
 
-DexCache* ClassLinker::FindDexCache(const DexFile* dex_file) const {
+DexCache* ClassLinker::FindDexCache(const DexFile& dex_file) const {
   for (size_t i = 0; i != dex_files_.size(); ++i) {
-    if (dex_files_[i] == dex_file) {
+    if (dex_files_[i] == &dex_file) {
         return dex_caches_[i];
     }
   }
@@ -815,7 +828,7 @@
 //
 // Returns NULL with an exception raised on failure.
 Class* ClassLinker::CreateArrayClass(const StringPiece& descriptor,
-                                     ClassLoader* class_loader)
+                                     const ClassLoader* class_loader)
 {
   CHECK(descriptor[0] == '[');
 
@@ -987,7 +1000,7 @@
   return ((*it).second == klass);
 }
 
-Class* ClassLinker::LookupClass(const StringPiece& descriptor, ClassLoader* class_loader) {
+Class* ClassLinker::LookupClass(const StringPiece& descriptor, const ClassLoader* class_loader) {
   size_t hash = StringPieceHash()(descriptor);
   MutexLock mu(classes_lock_);
   typedef Table::const_iterator It; // TODO: C++0x auto
@@ -1281,7 +1294,7 @@
         break;
       case DexFile::kString: {
         uint32_t string_idx = value.i;
-        String* resolved = ResolveString(klass, string_idx, dex_file);
+        String* resolved = ResolveString(dex_file, string_idx, klass->GetDexCache());
         field->SetObject(NULL, resolved);
         break;
       }
@@ -1320,8 +1333,8 @@
 
 bool ClassLinker::LoadSuperAndInterfaces(Class* klass, const DexFile& dex_file) {
   CHECK_EQ(Class::kStatusIdx, klass->status_);
-  if (klass->super_class_idx_ != DexFile::kDexNoIndex) {
-    Class* super_class = ResolveClass(klass, klass->super_class_idx_, dex_file);
+  if (klass->super_class_type_idx_ != DexFile::kDexNoIndex) {
+    Class* super_class = ResolveType(dex_file, klass->super_class_type_idx_, klass);
     if (super_class == NULL) {
       LG << "Failed to resolve superclass";
       return false;
@@ -1330,8 +1343,8 @@
   }
   if (klass->NumInterfaces() > 0) {
     for (size_t i = 0; i < klass->NumInterfaces(); ++i) {
-      uint32_t idx = klass->interfaces_idx_[i];
-      klass->SetInterface(i, ResolveClass(klass, idx, dex_file));
+      uint32_t type_idx = klass->interfaces_type_idx_[i];
+      klass->SetInterface(i, ResolveType(dex_file, type_idx, klass));
       if (klass->GetInterface(i) == NULL) {
         LG << "Failed to resolve interface";
         return false;
@@ -1798,50 +1811,98 @@
   }
 }
 
-Class* ClassLinker::ResolveClass(const Class* referrer,
-                                 uint32_t class_idx,
-                                 const DexFile& dex_file) {
-  DexCache* dex_cache = referrer->GetDexCache();
-  Class* resolved = dex_cache->GetResolvedClass(class_idx);
+String* ClassLinker::ResolveString(const DexFile& dex_file,
+                                   uint32_t string_idx,
+                                   DexCache* dex_cache) {
+  String* resolved = dex_cache->GetResolvedString(string_idx);
   if (resolved != NULL) {
     return resolved;
   }
-  const char* descriptor = dex_file.dexStringByTypeIdx(class_idx);
+  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* string = intern_table_.Intern(utf16_length, utf8_data);
+  dex_cache->SetResolvedString(string_idx, string);
+  return string;
+}
+
+Class* ClassLinker::ResolveType(const DexFile& dex_file,
+                                uint32_t type_idx,
+                                DexCache* dex_cache,
+                                const ClassLoader* class_loader) {
+  Class* resolved = dex_cache->GetResolvedType(type_idx);
+  if (resolved != NULL) {
+    return resolved;
+  }
+  const char* descriptor = dex_file.dexStringByTypeIdx(type_idx);
   if (descriptor[0] != '\0' && descriptor[1] == '\0') {
     resolved = FindPrimitiveClass(descriptor[0]);
   } else {
-    resolved = FindClass(descriptor, referrer->GetClassLoader());
+    resolved = FindClass(descriptor, class_loader);
   }
   if (resolved != NULL) {
     Class* check = resolved->IsArray() ? resolved->component_type_ : resolved;
-    if (referrer->GetDexCache() != check->GetDexCache()) {
+    if (dex_cache != check->GetDexCache()) {
       if (check->GetClassLoader() != NULL) {
         LG << "Class resolved by unexpected DEX";  // TODO: IllegalAccessError
         return NULL;
       }
     }
-    dex_cache->SetResolvedClass(class_idx, resolved);
+    dex_cache->SetResolvedType(type_idx, resolved);
   } else {
     DCHECK(Thread::Current()->IsExceptionPending());
   }
   return resolved;
 }
 
-Method* ResolveMethod(const Class* referrer, uint32_t method_idx,
-                      /*MethodType*/ int method_type) {
-  CHECK(false);
-  return NULL;
+Method* ClassLinker::ResolveMethod(const DexFile& dex_file,
+                                   uint32_t method_idx,
+                                   DexCache* dex_cache,
+                                   const ClassLoader* class_loader,
+                                   /*MethodType*/ int method_type) {
+  Method* resolved = dex_cache->GetResolvedMethod(method_idx);
+  if (resolved != NULL) {
+    return resolved;
+  }
+  const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
+  Class* klass = ResolveType(dex_file, method_id.class_idx_, dex_cache, class_loader);
+  if (klass == NULL) {
+    return NULL;
+  }
+
+  // TODO resolve using class, method_id, and method type.
+  // resolved = ...
+  if (resolved != NULL) {
+    dex_cache->SetResolvedMethod(method_idx, resolved);
+  } else {
+    // DCHECK(Thread::Current()->IsExceptionPending());
+  }
+  return resolved;
 }
 
-String* ClassLinker::ResolveString(const Class* referring,
-                                   uint32_t string_idx,
-                                   const DexFile& dex_file) {
-  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* string = intern_table_.Intern(utf16_length, utf8_data);
-  referring->GetDexCache()->SetResolvedString(string_idx, string);
-  return string;
+Field* ClassLinker::ResolveField(const DexFile& dex_file,
+                                 uint32_t field_idx,
+                                 DexCache* dex_cache,
+                                 const ClassLoader* class_loader,
+                                 bool is_static) {
+  Field* resolved = dex_cache->GetResolvedField(field_idx);
+  if (resolved != NULL) {
+    return resolved;
+  }
+  const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx);
+  Class* klass = ResolveType(dex_file, field_id.class_idx_, dex_cache, class_loader);
+  if (klass == NULL) {
+    return NULL;
+  }
+
+  // TODO resolve using class, field_id, and is_static.
+  // resolved = ...
+  if (resolved != NULL) {
+    dex_cache->SetResolvedfield(field_idx, resolved);
+  } else {
+    // DCHECK(Thread::Current()->IsExceptionPending());
+  }
+  return resolved;
 }
 
 }  // namespace art