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