Add DexCache table of <Method*, Method::GetCode()>

Change-Id: I69d46e61ff40456ff76888ad90b00e2036250d40
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 3c72dad..e0b55ca 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -425,15 +425,20 @@
 }
 
 DexCache* ClassLinker::AllocDexCache(const DexFile& dex_file) {
-  DexCache* dex_cache = down_cast<DexCache*>(AllocObjectArray<Object>(DexCache::kMax));
+  DexCache* dex_cache = down_cast<DexCache*>(AllocObjectArray<Object>(DexCache::LengthAsArray()));
   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()));
+                  AllocObjectArray<Field>(dex_file.NumFieldIds()),
+                  AllocCodeAndMethods(dex_file.NumMethodIds()));
   return dex_cache;
 }
 
+CodeAndMethods* ClassLinker::AllocCodeAndMethods(size_t length) {
+  return down_cast<CodeAndMethods*>(IntArray::Alloc(CodeAndMethods::LengthAsArray(length)));
+}
+
 Class* ClassLinker::AllocClass(Class* java_lang_Class, size_t class_size) {
   DCHECK_GE(class_size, sizeof(Class));
   Class* klass = Heap::AllocObject(java_lang_Class, class_size)->AsClass();
@@ -761,6 +766,7 @@
   dst->dex_cache_types_ = klass->dex_cache_->GetTypes();
   dst->dex_cache_methods_ = klass->dex_cache_->GetMethods();
   dst->dex_cache_fields_ = klass->dex_cache_->GetFields();
+  dst->dex_cache_code_and_methods_ = klass->dex_cache_->GetCodeAndMethods();
 
   // TODO: check for finalize method
 
diff --git a/src/class_linker.h b/src/class_linker.h
index 88e1a67..eb40d28 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -135,6 +135,7 @@
   ObjectArray<T>* AllocObjectArray(size_t length) {
     return ObjectArray<T>::Alloc(GetClassRoot(kObjectArrayClass), length);
   }
+  CodeAndMethods* AllocCodeAndMethods(size_t length);
 
   Class* CreatePrimitiveClass(const char* descriptor);
 
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index 9e96439..c1ef7b7 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -103,10 +103,13 @@
     EXPECT_TRUE(method->dex_cache_types_ != NULL);
     EXPECT_TRUE(method->dex_cache_methods_ != NULL);
     EXPECT_TRUE(method->dex_cache_fields_ != NULL);
+    EXPECT_TRUE(method->dex_cache_code_and_methods_ != NULL);
     EXPECT_EQ(method->declaring_class_->dex_cache_->GetStrings(), method->dex_cache_strings_);
     EXPECT_EQ(method->declaring_class_->dex_cache_->GetTypes(), method->dex_cache_types_);
     EXPECT_EQ(method->declaring_class_->dex_cache_->GetMethods(), method->dex_cache_methods_);
     EXPECT_EQ(method->declaring_class_->dex_cache_->GetFields(), method->dex_cache_fields_);
+    EXPECT_EQ(method->declaring_class_->dex_cache_->GetCodeAndMethods(),
+              method->dex_cache_code_and_methods_);
   }
 
   void AssertField(Class* klass, Field* field) {
diff --git a/src/compiler.cc b/src/compiler.cc
index 57edf53..d1605a7 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -15,11 +15,9 @@
 const ClassLoader* Compiler::Compile(std::vector<const DexFile*> class_path) {
   const ClassLoader* class_loader = PathClassLoader::Alloc(class_path);
   Resolve(class_loader);
-  for (size_t i = 0; i != class_path.size(); ++i) {
-    const DexFile* dex_file = class_path[i];
-    CHECK(dex_file != NULL);
-    CompileDexFile(class_loader, *dex_file);
-  }
+  // TODO add verification step
+  Compile(class_loader);
+  SetCodeAndMethod(class_loader);
   return class_loader;
 }
 
@@ -61,6 +59,15 @@
   }
 }
 
+void Compiler::Compile(const ClassLoader* class_loader) {
+  const std::vector<const DexFile*>& class_path = class_loader->GetClassPath();
+  for (size_t i = 0; i != class_path.size(); ++i) {
+    const DexFile* dex_file = class_path[i];
+    CHECK(dex_file != NULL);
+    CompileDexFile(class_loader, *dex_file);
+  }
+}
+
 void Compiler::CompileDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   for (size_t i = 0; i < dex_file.NumClassDefs(); i++) {
@@ -97,4 +104,25 @@
   // CHECK(method->HasCode());  // TODO: enable this check ASAP
 }
 
+void Compiler::SetCodeAndMethod(const ClassLoader* class_loader) {
+  const std::vector<const DexFile*>& class_path = class_loader->GetClassPath();
+  for (size_t i = 0; i != class_path.size(); ++i) {
+    const DexFile* dex_file = class_path[i];
+    CHECK(dex_file != NULL);
+    SetCodeAndMethodDexFile(class_loader, *dex_file);
+  }
+}
+
+void Compiler::SetCodeAndMethodDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  DexCache* dex_cache = class_linker->FindDexCache(dex_file);
+  CodeAndMethods* code_and_methods = dex_cache->GetCodeAndMethods();
+  for (size_t i = 0; i < dex_cache->NumMethods(); i++) {
+    Method* method = dex_cache->GetResolvedMethod(i);
+    if (method != NULL) {
+      code_and_methods->SetResolvedMethod(i, method);
+    }
+  }
+}
+
 }  // namespace art
diff --git a/src/compiler.h b/src/compiler.h
index e779646..864f29d 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -22,9 +22,15 @@
   void Resolve(const ClassLoader* class_loader);
   void ResolveDexFile(const ClassLoader* class_loader, const DexFile& dex_file);
 
+  void Compile(const ClassLoader* class_loader);
   void CompileDexFile(const ClassLoader* class_loader, const DexFile& dex_file);
   void CompileClass(Class* klass);
   void CompileMethod(Method* klass);
+
+  // After compiling, walk all the DexCaches and set the code and
+  // method pointers of CodeAndMethod entries in the DexCaches.
+  void SetCodeAndMethod(const ClassLoader* class_loader);
+  void SetCodeAndMethodDexFile(const ClassLoader* class_loader, const DexFile& dex_file);
 };
 
 }  // namespace art
diff --git a/src/compiler_test.cc b/src/compiler_test.cc
index 63aeee2..cab932f 100644
--- a/src/compiler_test.cc
+++ b/src/compiler_test.cc
@@ -95,6 +95,17 @@
     EXPECT_TRUE(field != NULL);
   }
 
+  // TODO check Class::IsVerified for all classes
+
+  // TODO: check that all Method::GetCode() values are non-null
+
+  EXPECT_EQ(dex->NumMethodIds(), dex_cache->NumCodeAndMethods());
+  CodeAndMethods* code_and_methods = dex_cache->GetCodeAndMethods();
+  for (size_t i = 0; i < dex_cache->NumCodeAndMethods(); i++) {
+    Method* method = dex_cache->GetResolvedMethod(i);
+    EXPECT_EQ(method->GetCode(), code_and_methods->GetResolvedCode(i));
+    EXPECT_EQ(method,            code_and_methods->GetResolvedMethod(i));
+  }
 }
 
 TEST_F(CompilerTest, BasicCodegen) {
diff --git a/src/dex_cache.cc b/src/dex_cache.cc
index a012c71..88fbd2f 100644
--- a/src/dex_cache.cc
+++ b/src/dex_cache.cc
@@ -13,12 +13,20 @@
                     ObjectArray<String>* strings,
                     ObjectArray<Class>* types,
                     ObjectArray<Method>* methods,
-                    ObjectArray<Field>* fields) {
-  Set(kLocation, location);
-  Set(kStrings,  strings);
-  Set(kTypes,    types);
-  Set(kMethods,  methods);
-  Set(kFields,   fields);
+                    ObjectArray<Field>* fields,
+                    CodeAndMethods* code_and_methods) {
+  CHECK(location != NULL);
+  CHECK(strings != NULL);
+  CHECK(types != NULL);
+  CHECK(methods != NULL);
+  CHECK(fields != NULL);
+  CHECK(code_and_methods != NULL);
+  Set(kLocation,       location);
+  Set(kStrings,        strings);
+  Set(kTypes,          types);
+  Set(kMethods,        methods);
+  Set(kFields,         fields);
+  Set(kCodeAndMethods, code_and_methods);
 }
 
 }  // namespace art
diff --git a/src/dex_cache.h b/src/dex_cache.h
index 9e762e1..2f75c86 100644
--- a/src/dex_cache.h
+++ b/src/dex_cache.h
@@ -16,23 +16,43 @@
 class String;
 union JValue;
 
-class DexCache : public ObjectArray<Object> {
+class CodeAndMethods : public IntArray {
  public:
+  Method* GetResolvedCode(uint32_t method_idx) const {
+    return reinterpret_cast<Method*>(Get(method_idx * kMax + kCode));
+  }
+  void* GetResolvedMethod(uint32_t method_idx) const {
+    return reinterpret_cast<byte*>(Get(method_idx * kMax + kMethod));
+  }
 
-  enum ArrayIndex {
-    kLocation = 0,
-    kStrings  = 1,
-    kTypes    = 2,
-    kMethods  = 3,
-    kFields   = 4,
-    kMax      = 5,
+  void SetResolvedMethod(uint32_t method_idx, Method* method) {
+    CHECK(method != NULL);
+    // CHECK(method->GetCode() != NULL);  // TODO enable when all code is compiling
+    Set(method_idx * kMax + kCode,   reinterpret_cast<int32_t>(method->GetCode()));
+    Set(method_idx * kMax + kMethod, reinterpret_cast<int32_t>(method));
+  }
+
+ static size_t LengthAsArray(size_t elements) {
+   return kMax * elements;
+ }
+
+ private:
+  enum TupleIndex {
+    kCode   = 0,
+    kMethod = 1,
+    kMax    = 2,
   };
 
+};
+
+class DexCache : public ObjectArray<Object> {
+ public:
   void Init(String* location,
             ObjectArray<String>* strings,
             ObjectArray<Class>* types,
             ObjectArray<Method>* methods,
-            ObjectArray<Field>* fields);
+            ObjectArray<Field>* fields,
+            CodeAndMethods* code_and_methods);
 
   String* GetLocation() const {
     return Get(kLocation)->AsString();
@@ -69,6 +89,10 @@
     return GetFields()->GetLength();
   }
 
+  size_t NumCodeAndMethods() const {
+    return GetCodeAndMethods()->GetLength();
+  }
+
   String* GetResolvedString(uint32_t string_idx) const {
     return GetStrings()->Get(string_idx);
   }
@@ -113,8 +137,26 @@
   ObjectArray<Field>* GetFields() const {
     return static_cast<ObjectArray<Field>*>(GetNonNull(kFields));
   }
+  CodeAndMethods* GetCodeAndMethods() const {
+    return static_cast<CodeAndMethods*>(GetNonNull(kCodeAndMethods));
+  }
+
+ static size_t LengthAsArray() {
+   return kMax;
+ }
 
  private:
+
+  enum ArrayIndex {
+    kLocation       = 0,
+    kStrings        = 1,
+    kTypes          = 2,
+    kMethods        = 3,
+    kFields         = 4,
+    kCodeAndMethods = 5,
+    kMax            = 6,
+  };
+
   Object* GetNonNull(ArrayIndex array_index) const {
     Object* obj = Get(array_index);
     DCHECK(obj != NULL);
diff --git a/src/object.h b/src/object.h
index e306d74..9db0704 100644
--- a/src/object.h
+++ b/src/object.h
@@ -18,6 +18,7 @@
 
 class Array;
 class Class;
+class CodeAndMethods;
 class DexCache;
 class Field;
 class InterfaceEntry;
@@ -586,6 +587,10 @@
     return code_ != NULL;
   }
 
+  const void* GetCode() {
+    return code_;
+  }
+
   void SetCode(const byte* compiled_code,
                size_t byte_count,
                InstructionSet set) {
@@ -714,12 +719,13 @@
   ObjectArray<Class>* dex_cache_types_;
   ObjectArray<Method>* dex_cache_methods_;
   ObjectArray<Field>* dex_cache_fields_;
+  CodeAndMethods* dex_cache_code_and_methods_;
 
  private:
   // Compiled code associated with this method
   scoped_ptr<MemMap> code_area_;
-  void* code_;
-  // Instruction set of the coompiled code
+  const void* code_;
+  // Instruction set of the compiled code
   InstructionSet code_instruction_set_;
 
   // Size in bytes of compiled code associated with this method