summaryrefslogtreecommitdiff
path: root/src/compiler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler.cc')
-rw-r--r--src/compiler.cc244
1 files changed, 136 insertions, 108 deletions
diff --git a/src/compiler.cc b/src/compiler.cc
index ba61b4d968..96beaa6148 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -14,20 +14,20 @@
#include "runtime.h"
#include "stl_util.h"
-extern art::CompiledMethod* oatCompileMethod(const art::Compiler& compiler,
- const art::Method*,
- art::InstructionSet);
+art::CompiledMethod* oatCompileMethod(const art::Compiler& compiler, bool is_direct,
+ uint32_t method_idx, const art::ClassLoader* class_loader,
+ const art::DexFile& dex_file, art::InstructionSet);
namespace art {
namespace arm {
ByteArray* CreateAbstractMethodErrorStub();
- CompiledInvokeStub* ArmCreateInvokeStub(const Method* method);
+ CompiledInvokeStub* ArmCreateInvokeStub(bool is_static, const char* shorty);
ByteArray* ArmCreateResolutionTrampoline(Runtime::TrampolineType type);
}
namespace x86 {
ByteArray* CreateAbstractMethodErrorStub();
- CompiledInvokeStub* X86CreateInvokeStub(const Method* method);
+ CompiledInvokeStub* X86CreateInvokeStub(bool is_static, const char* shorty);
ByteArray* X86CreateResolutionTrampoline(Runtime::TrampolineType type);
}
@@ -80,7 +80,12 @@ void Compiler::CompileOne(const Method* method) {
Resolve(class_loader);
Verify(class_loader);
InitializeClassesWithoutClinit(class_loader);
- CompileMethod(method);
+ // Find the dex_file
+ const DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
+ const DexFile& dex_file = Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache);
+ uint32_t method_idx = method->GetDexMethodIndex();
+ CompileMethod(method->IsDirect(), method->IsNative(), method->IsStatic(), method->IsAbstract(),
+ method_idx, class_loader, dex_file);
SetCodeAndDirectMethods(class_loader);
}
@@ -127,69 +132,52 @@ void Compiler::ResolveDexFile(const ClassLoader* class_loader, const DexFile& de
// static fields, instance fields, direct methods, and virtual
// methods.
const byte* class_data = dex_file.GetClassData(class_def);
-
- DexFile::ClassDataHeader header = dex_file.ReadClassDataHeader(&class_data);
- size_t num_static_fields = header.static_fields_size_;
- size_t num_instance_fields = header.instance_fields_size_;
- size_t num_direct_methods = header.direct_methods_size_;
- size_t num_virtual_methods = header.virtual_methods_size_;
-
- if (num_static_fields != 0) {
- uint32_t last_idx = 0;
- for (size_t i = 0; i < num_static_fields; ++i) {
- DexFile::Field dex_field;
- dex_file.dexReadClassDataField(&class_data, &dex_field, &last_idx);
- Field* field = class_linker->ResolveField(dex_file, dex_field.field_idx_, dex_cache,
- class_loader, true);
- if (field == NULL) {
- Thread* self = Thread::Current();
- CHECK(self->IsExceptionPending());
- self->ClearException();
- }
+ if (class_data == NULL) {
+ // empty class such as a marker interface
+ continue;
+ }
+ ClassDataItemIterator it(dex_file, class_data);
+ while (it.HasNextStaticField()) {
+ Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
+ class_loader, true);
+ if (field == NULL) {
+ Thread* self = Thread::Current();
+ CHECK(self->IsExceptionPending());
+ self->ClearException();
}
+ it.Next();
}
- if (num_instance_fields != 0) {
- uint32_t last_idx = 0;
- for (size_t i = 0; i < num_instance_fields; ++i) {
- DexFile::Field dex_field;
- dex_file.dexReadClassDataField(&class_data, &dex_field, &last_idx);
- Field* field = class_linker->ResolveField(dex_file, dex_field.field_idx_, dex_cache,
- class_loader, false);
- if (field == NULL) {
- Thread* self = Thread::Current();
- CHECK(self->IsExceptionPending());
- self->ClearException();
- }
+ while (it.HasNextInstanceField()) {
+ Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
+ class_loader, false);
+ if (field == NULL) {
+ Thread* self = Thread::Current();
+ CHECK(self->IsExceptionPending());
+ self->ClearException();
}
+ it.Next();
}
- if (num_direct_methods != 0) {
- uint32_t last_idx = 0;
- for (size_t i = 0; i < num_direct_methods; ++i) {
- DexFile::Method dex_method;
- dex_file.dexReadClassDataMethod(&class_data, &dex_method, &last_idx);
- Method* method = class_linker->ResolveMethod(dex_file, dex_method.method_idx_, dex_cache,
- class_loader, true);
- if (method == NULL) {
- Thread* self = Thread::Current();
- CHECK(self->IsExceptionPending());
- self->ClearException();
- }
+ while (it.HasNextDirectMethod()) {
+ Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
+ class_loader, true);
+ if (method == NULL) {
+ Thread* self = Thread::Current();
+ CHECK(self->IsExceptionPending());
+ self->ClearException();
}
+ it.Next();
}
- if (num_virtual_methods != 0) {
- uint32_t last_idx = 0;
- for (size_t i = 0; i < num_virtual_methods; ++i) {
- DexFile::Method dex_method;
- dex_file.dexReadClassDataMethod(&class_data, &dex_method, &last_idx);
- Method* method = class_linker->ResolveMethod(dex_file, dex_method.method_idx_, dex_cache,
- class_loader, false);
- if (method == NULL) {
- Thread* self = Thread::Current();
- CHECK(self->IsExceptionPending());
- self->ClearException();
- }
+ while (it.HasNextVirtualMethod()) {
+ Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
+ class_loader, false);
+ if (method == NULL) {
+ Thread* self = Thread::Current();
+ CHECK(self->IsExceptionPending());
+ self->ClearException();
}
+ it.Next();
}
+ DCHECK(!it.HasNext());
}
}
@@ -278,78 +266,118 @@ void Compiler::Compile(const ClassLoader* class_loader) {
}
void Compiler::CompileDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
- const char* descriptor = dex_file.GetClassDescriptor(class_def);
- Class* klass = class_linker->FindClass(descriptor, class_loader);
- if (klass == NULL) {
- // previous verification error will cause FindClass to throw
- Thread* self = Thread::Current();
- CHECK(self->IsExceptionPending());
- self->ClearException();
- } else {
- CompileClass(klass);
- }
+ CompileClass(class_def, class_loader, dex_file);
}
}
-void Compiler::CompileClass(const Class* klass) {
- for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
- CompileMethod(klass->GetDirectMethod(i));
+void Compiler::CompileClass(const DexFile::ClassDef& class_def, const ClassLoader* class_loader,
+ const DexFile& dex_file) {
+ const byte* class_data = dex_file.GetClassData(class_def);
+ if (class_data == NULL) {
+ // empty class, probably a marker interface
+ return;
+ }
+ ClassDataItemIterator it(dex_file, class_data);
+ // Skip fields
+ while (it.HasNextStaticField()) {
+ it.Next();
+ }
+ while (it.HasNextInstanceField()) {
+ it.Next();
+ }
+ // Compile direct methods
+ while (it.HasNextDirectMethod()) {
+ bool is_native = (it.GetMemberAccessFlags() & kAccNative) != 0;
+ bool is_static = (it.GetMemberAccessFlags() & kAccStatic) != 0;
+ bool is_abstract = (it.GetMemberAccessFlags() & kAccAbstract) != 0;
+ CompileMethod(true, is_native, is_static, is_abstract, it.GetMemberIndex(), class_loader,
+ dex_file);
+ it.Next();
}
- for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
- CompileMethod(klass->GetVirtualMethod(i));
+ // Compile virtual methods
+ while (it.HasNextVirtualMethod()) {
+ bool is_native = (it.GetMemberAccessFlags() & kAccNative) != 0;
+ bool is_static = (it.GetMemberAccessFlags() & kAccStatic) != 0;
+ bool is_abstract = (it.GetMemberAccessFlags() & kAccAbstract) != 0;
+ CompileMethod(false, is_native, is_static, is_abstract, it.GetMemberIndex(), class_loader,
+ dex_file);
+ it.Next();
}
+ DCHECK(!it.HasNext());
}
-void Compiler::CompileMethod(const Method* method) {
+void Compiler::CompileMethod(bool is_direct, bool is_native, bool is_static, bool is_abstract,
+ uint32_t method_idx, const ClassLoader* class_loader,
+ const DexFile& dex_file) {
CompiledMethod* compiled_method = NULL;
- if (method->IsNative()) {
- compiled_method = jni_compiler_.Compile(method);
+ if (is_native) {
+ compiled_method = jni_compiler_.Compile(is_direct, method_idx, class_loader, dex_file);
CHECK(compiled_method != NULL);
- } else if (method->IsAbstract()) {
+ } else if (is_abstract) {
} else {
- compiled_method = oatCompileMethod(*this, method, kThumb2);
- CHECK(compiled_method != NULL);
+ compiled_method = oatCompileMethod(*this, is_direct, method_idx, class_loader, dex_file,
+ kThumb2);
+ // TODO: assert compiled_method is not NULL, currently NULL may be returned if the method
+ // wasn't resolved
}
if (compiled_method != NULL) {
- CHECK(compiled_methods_.find(method) == compiled_methods_.end()) << PrettyMethod(method);
- compiled_methods_[method] = compiled_method;
- DCHECK(compiled_methods_.find(method) != compiled_methods_.end()) << PrettyMethod(method);
- DCHECK(GetCompiledMethod(method) != NULL) << PrettyMethod(method);
+ MethodReference ref(&dex_file, method_idx);
+ CHECK(compiled_methods_.find(ref) == compiled_methods_.end())
+ << PrettyMethod(method_idx, dex_file);
+ compiled_methods_[ref] = compiled_method;
+ DCHECK(compiled_methods_.find(ref) != compiled_methods_.end())
+ << PrettyMethod(method_idx, dex_file);
+ DCHECK(GetCompiledMethod(ref) != NULL)
+ << PrettyMethod(method_idx, dex_file);
}
- CompiledInvokeStub* compiled_invoke_stub = NULL;
- if (instruction_set_ == kX86) {
- compiled_invoke_stub = art::x86::X86CreateInvokeStub(method);
- } else {
- CHECK(instruction_set_ == kArm || instruction_set_ == kThumb2);
- // Generates invocation stub using ARM instruction set
- compiled_invoke_stub = art::arm::ArmCreateInvokeStub(method);
+ const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
+ const CompiledInvokeStub* compiled_invoke_stub = FindInvokeStub(is_static, shorty);
+ if (compiled_invoke_stub == NULL) {
+ if (instruction_set_ == kX86) {
+ compiled_invoke_stub = art::x86::X86CreateInvokeStub(is_static, shorty);
+ } else {
+ CHECK(instruction_set_ == kArm || instruction_set_ == kThumb2);
+ // Generates invocation stub using ARM instruction set
+ compiled_invoke_stub = art::arm::ArmCreateInvokeStub(is_static, shorty);
+ }
+ CHECK(compiled_invoke_stub != NULL);
+ InsertInvokeStub(is_static, shorty, compiled_invoke_stub);
}
- CHECK(compiled_invoke_stub != NULL);
- // TODO: this fails if we have an abstract method defined in more than one input dex file.
- CHECK(compiled_invoke_stubs_.find(method) == compiled_invoke_stubs_.end()) << PrettyMethod(method);
- compiled_invoke_stubs_[method] = compiled_invoke_stub;
+ CHECK(!Thread::Current()->IsExceptionPending()) << PrettyMethod(method_idx, dex_file);
+}
- Thread* self = Thread::Current();
- CHECK(!self->IsExceptionPending()) << PrettyMethod(method);
+static std::string MakeInvokeStubKey(bool is_static, const char* shorty) {
+ std::string key(shorty);
+ if (is_static) {
+ key += "$"; // musn't be a shorty type character
+ }
+ return key;
}
-const CompiledMethod* Compiler::GetCompiledMethod(const Method* method) const {
- MethodTable::const_iterator it = compiled_methods_.find(method);
- if (it == compiled_methods_.end()) {
+const CompiledInvokeStub* Compiler::FindInvokeStub(bool is_static, const char* shorty) const {
+ std::string key = MakeInvokeStubKey(is_static, shorty);
+ InvokeStubTable::const_iterator it = compiled_invoke_stubs_.find(key);
+ if (it == compiled_invoke_stubs_.end()) {
return NULL;
+ } else {
+ DCHECK(it->second != NULL);
+ return it->second;
}
- CHECK(it->second != NULL);
- return it->second;
}
-const CompiledInvokeStub* Compiler::GetCompiledInvokeStub(const Method* method) const {
- InvokeStubTable::const_iterator it = compiled_invoke_stubs_.find(method);
- if (it == compiled_invoke_stubs_.end()) {
+void Compiler::InsertInvokeStub(bool is_static, const char* shorty,
+ const CompiledInvokeStub* compiled_invoke_stub) {
+ std::string key = MakeInvokeStubKey(is_static, shorty);
+ compiled_invoke_stubs_[key] = compiled_invoke_stub;
+}
+
+CompiledMethod* Compiler::GetCompiledMethod(MethodReference ref) const {
+ MethodTable::const_iterator it = compiled_methods_.find(ref);
+ if (it == compiled_methods_.end()) {
return NULL;
}
CHECK(it->second != NULL);