summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Ian Rogers <irogers@google.com> 2011-11-03 19:51:38 -0700
committer Ian Rogers <irogers@google.com> 2011-11-13 11:57:18 -0800
commit0571d357843c53e042f370f5f2c2e9aa3fe803a9 (patch)
tree197e5b1c0b1bf0ee8cc0e1960470d0a8d203b4af
parent33dc7717cd16592bcc825350bea6305be9eb2ea1 (diff)
Refactor the use of Method by the compiler.
Remove the dependence on the Method object in dex2oat, allowing lazier resolution. Introduce new find and iterators in DexFile to simplify common operations and avoid misuse of class data items. Change-Id: I39fb8252190f543d89d8b233076355cec310fe08
-rw-r--r--build/Android.common.mk2
-rw-r--r--src/calling_convention.h2
-rw-r--r--src/calling_convention_arm.cc5
-rw-r--r--src/calling_convention_arm.h1
-rw-r--r--src/calling_convention_x86.cc5
-rw-r--r--src/calling_convention_x86.h1
-rw-r--r--src/class_linker.cc231
-rw-r--r--src/class_linker.h12
-rw-r--r--src/common_test.h12
-rw-r--r--src/compiled_method.cc9
-rw-r--r--src/compiled_method.h5
-rw-r--r--src/compiler.cc244
-rw-r--r--src/compiler.h38
-rw-r--r--src/compiler/Compiler.h8
-rw-r--r--src/compiler/Frontend.cc48
-rw-r--r--src/compiler/codegen/arm/Thumb2/Gen.cc4
-rw-r--r--src/dex_cache.cc8
-rw-r--r--src/dex_cache.h8
-rw-r--r--src/dex_file.cc621
-rw-r--r--src/dex_file.h932
-rw-r--r--src/dex_file_test.cc111
-rw-r--r--src/dex_verifier.cc60
-rw-r--r--src/exception_test.cc44
-rw-r--r--src/image_test.cc8
-rw-r--r--src/jni_compiler.cc9
-rw-r--r--src/jni_compiler.h3
-rw-r--r--src/jni_internal.cc83
-rw-r--r--src/jni_internal.h1
-rw-r--r--src/jni_internal_arm.cc26
-rw-r--r--src/jni_internal_x86.cc15
-rw-r--r--src/monitor.cc2
-rw-r--r--src/oat.cc3
-rw-r--r--src/oat.h2
-rw-r--r--src/oat_file.cc3
-rw-r--r--src/oat_file.h2
-rw-r--r--src/oat_test.cc19
-rw-r--r--src/oat_writer.cc294
-rw-r--r--src/oat_writer.h29
-rw-r--r--src/oatdump.cc62
-rw-r--r--src/object.cc79
-rw-r--r--src/object.h30
-rw-r--r--src/runtime_support.cc10
-rw-r--r--src/utf.cc14
-rw-r--r--src/utf.h5
-rw-r--r--src/utils.cc13
-rw-r--r--src/utils.h2
-rw-r--r--test/CreateMethodSignature/CreateMethodSignature.java (renamed from test/CreateMethodDescriptor/CreateMethodDescriptor.java)4
47 files changed, 1814 insertions, 1315 deletions
diff --git a/build/Android.common.mk b/build/Android.common.mk
index 968228bf48..4b0cdfec0e 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -247,7 +247,7 @@ TEST_HOST_SRC_FILES := \
TEST_DEX_DIRECTORIES := \
AbstractMethod \
AllFields \
- CreateMethodDescriptor \
+ CreateMethodSignature \
ExceptionHandle \
ExceptionTest \
Fibonacci \
diff --git a/src/calling_convention.h b/src/calling_convention.h
index 3a7cf1ed1e..7e87264159 100644
--- a/src/calling_convention.h
+++ b/src/calling_convention.h
@@ -124,8 +124,6 @@ class JniCallingConvention : public CallingConvention {
// always at the bottom of a frame, but this doesn't work for outgoing
// native args). Includes alignment.
virtual size_t FrameSize() = 0;
- // Offset within the frame of the return pc
- virtual size_t ReturnPcOffset() = 0;
// Size of outgoing arguments, including alignment
virtual size_t OutArgSize() = 0;
// Number of references in stack indirect reference table
diff --git a/src/calling_convention_arm.cc b/src/calling_convention_arm.cc
index 89d41700f8..fc8c662f73 100644
--- a/src/calling_convention_arm.cc
+++ b/src/calling_convention_arm.cc
@@ -146,11 +146,6 @@ size_t ArmJniCallingConvention::OutArgSize() {
kStackAlignment);
}
-size_t ArmJniCallingConvention::ReturnPcOffset() {
- // Link register is always the first value pushed when the frame is constructed
- return FrameSize() - kPointerSize;
-}
-
// Will reg be crushed by an outgoing argument?
bool ArmJniCallingConvention::IsMethodRegisterClobberedPreCall() {
return true; // The method register R0 is always clobbered by the JNIEnv
diff --git a/src/calling_convention_arm.h b/src/calling_convention_arm.h
index 2a056a82c3..4ecf9df562 100644
--- a/src/calling_convention_arm.h
+++ b/src/calling_convention_arm.h
@@ -37,7 +37,6 @@ class ArmJniCallingConvention : public JniCallingConvention {
// JNI calling convention
virtual void Next(); // Override default behavior for AAPCS
virtual size_t FrameSize();
- virtual size_t ReturnPcOffset();
virtual size_t OutArgSize();
virtual const std::vector<ManagedRegister>& CalleeSaveRegisters() const {
return callee_save_regs_;
diff --git a/src/calling_convention_x86.cc b/src/calling_convention_x86.cc
index da76e177c7..07ccece956 100644
--- a/src/calling_convention_x86.cc
+++ b/src/calling_convention_x86.cc
@@ -84,11 +84,6 @@ size_t X86JniCallingConvention::OutArgSize() {
return RoundUp(NumberOfOutgoingStackArgs() * kPointerSize, kStackAlignment);
}
-size_t X86JniCallingConvention::ReturnPcOffset() {
- // Return PC is pushed at the top of the frame by the call into the method
- return FrameSize() - kPointerSize;
-}
-
bool X86JniCallingConvention::IsMethodRegisterClobberedPreCall() {
return GetMethod()->IsSynchronized(); // Monitor enter crushes the method register
}
diff --git a/src/calling_convention_x86.h b/src/calling_convention_x86.h
index b796ba0d5a..f3c85e92f5 100644
--- a/src/calling_convention_x86.h
+++ b/src/calling_convention_x86.h
@@ -37,7 +37,6 @@ class X86JniCallingConvention : public JniCallingConvention {
virtual ManagedRegister InterproceduralScratchRegister();
// JNI calling convention
virtual size_t FrameSize();
- virtual size_t ReturnPcOffset();
virtual size_t OutArgSize();
virtual const std::vector<ManagedRegister>& CalleeSaveRegisters() const {
DCHECK(callee_save_regs_.empty());
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 4f387db472..584c53ebf0 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -14,6 +14,7 @@
#include "dex_verifier.h"
#include "heap.h"
#include "intern_table.h"
+#include "leb128.h"
#include "logging.h"
#include "monitor.h"
#include "oat_file.h"
@@ -1070,17 +1071,12 @@ Class* ClassLinker::DefineClass(const std::string& descriptor,
size_t ClassLinker::SizeOfClass(const DexFile& dex_file,
const DexFile::ClassDef& dex_class_def) {
const byte* class_data = dex_file.GetClassData(dex_class_def);
- DexFile::ClassDataHeader header = dex_file.ReadClassDataHeader(&class_data);
- size_t num_static_fields = header.static_fields_size_;
size_t num_ref = 0;
size_t num_32 = 0;
size_t num_64 = 0;
- 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);
- const DexFile::FieldId& field_id = dex_file.GetFieldId(dex_field.field_idx_);
+ if (class_data != NULL) {
+ for (ClassDataItemIterator it(dex_file, class_data); it.HasNextStaticField(); it.Next()) {
+ const DexFile::FieldId& field_id = dex_file.GetFieldId(it.GetMemberIndex());
const char* descriptor = dex_file.GetFieldTypeDescriptor(field_id);
char c = descriptor[0];
if (c == 'L' || c == '[') {
@@ -1092,7 +1088,6 @@ size_t ClassLinker::SizeOfClass(const DexFile& dex_file,
}
}
}
-
// start with generic class data
size_t size = sizeof(Class);
// follow with reference fields which must be contiguous at start
@@ -1137,9 +1132,6 @@ void ClassLinker::LoadClass(const DexFile& dex_file,
CHECK(klass.get() != NULL);
CHECK(klass->GetDexCache() != NULL);
CHECK_EQ(Class::kStatusNotReady, klass->GetStatus());
- const byte* class_data = dex_file.GetClassData(dex_class_def);
- DexFile::ClassDataHeader header = dex_file.ReadClassDataHeader(&class_data);
-
const char* descriptor = dex_file.GetClassDescriptor(dex_class_def);
CHECK(descriptor != NULL);
@@ -1164,12 +1156,7 @@ void ClassLinker::LoadClass(const DexFile& dex_file,
klass->SetSuperClassTypeIdx(dex_class_def.superclass_idx_);
klass->SetAnnotationsOffset(dex_class_def.annotations_off_);
- 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_;
-
- const char* source_file = dex_file.dexGetSourceFile(dex_class_def);
+ const char* source_file = dex_file.GetSourceFile(dex_class_def);
if (source_file != NULL) {
String* source_file_string = intern_table_->InternStrong(source_file);
if (source_file_string == NULL) {
@@ -1181,30 +1168,27 @@ void ClassLinker::LoadClass(const DexFile& dex_file,
// Load class interfaces.
LoadInterfaces(dex_file, dex_class_def, klass);
- // Load static fields.
- if (num_static_fields != 0) {
- klass->SetSFields(AllocObjectArray<Field>(num_static_fields));
- 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);
- SirtRef<Field> sfield(AllocField());
- klass->SetStaticField(i, sfield.get());
- LoadField(dex_file, dex_field, klass, sfield);
- }
+ // Load fields fields.
+ const byte* class_data = dex_file.GetClassData(dex_class_def);
+ if (class_data == NULL) {
+ return; // no fields or methods - for example a marker interface
}
-
- // Load instance fields.
- if (num_instance_fields != 0) {
- klass->SetIFields(AllocObjectArray<Field>(num_instance_fields));
- 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);
- SirtRef<Field> ifield(AllocField());
- klass->SetInstanceField(i, ifield.get());
- LoadField(dex_file, dex_field, klass, ifield);
- }
+ ClassDataItemIterator it(dex_file, class_data);
+ if (it.NumStaticFields() != 0) {
+ klass->SetSFields(AllocObjectArray<Field>(it.NumStaticFields()));
+ }
+ if (it.NumInstanceFields() != 0) {
+ klass->SetIFields(AllocObjectArray<Field>(it.NumInstanceFields()));
+ }
+ for (size_t i = 0; it.HasNextStaticField(); i++, it.Next()) {
+ SirtRef<Field> sfield(AllocField());
+ klass->SetStaticField(i, sfield.get());
+ LoadField(dex_file, it, klass, sfield);
+ }
+ for (size_t i = 0; it.HasNextInstanceField(); i++, it.Next()) {
+ SirtRef<Field> ifield(AllocField());
+ klass->SetInstanceField(i, ifield.get());
+ LoadField(dex_file, it, klass, ifield);
}
UniquePtr<const OatFile::OatClass> oat_class;
@@ -1221,41 +1205,35 @@ void ClassLinker::LoadClass(const DexFile& dex_file,
}
}
}
- size_t method_index = 0;
-
- // Load direct methods.
- if (num_direct_methods != 0) {
+ // Load methods.
+ if (it.NumDirectMethods() != 0) {
// TODO: append direct methods to class object
- klass->SetDirectMethods(AllocObjectArray<Method>(num_direct_methods));
- uint32_t last_idx = 0;
- for (size_t i = 0; i < num_direct_methods; ++i, ++method_index) {
- DexFile::Method dex_method;
- dex_file.dexReadClassDataMethod(&class_data, &dex_method, &last_idx);
- SirtRef<Method> method(AllocMethod());
- klass->SetDirectMethod(i, method.get());
- LoadMethod(dex_file, dex_method, klass, method);
- if (oat_class.get() != NULL) {
- LinkCode(method, oat_class.get(), method_index);
- }
+ klass->SetDirectMethods(AllocObjectArray<Method>(it.NumDirectMethods()));
+ }
+ if (it.NumVirtualMethods() != 0) {
+ // TODO: append direct methods to class object
+ klass->SetVirtualMethods(AllocObjectArray<Method>(it.NumVirtualMethods()));
+ }
+ size_t method_index = 0;
+ for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) {
+ SirtRef<Method> method(AllocMethod());
+ klass->SetDirectMethod(i, method.get());
+ LoadMethod(dex_file, it, klass, method);
+ if (oat_class.get() != NULL) {
+ LinkCode(method, oat_class.get(), method_index);
}
+ method_index++;
}
-
- // Load virtual methods.
- if (num_virtual_methods != 0) {
- // TODO: append virtual methods to class object
- klass->SetVirtualMethods(AllocObjectArray<Method>(num_virtual_methods));
- uint32_t last_idx = 0;
- for (size_t i = 0; i < num_virtual_methods; ++i, ++method_index) {
- DexFile::Method dex_method;
- dex_file.dexReadClassDataMethod(&class_data, &dex_method, &last_idx);
- SirtRef<Method> method(AllocMethod());
- klass->SetVirtualMethod(i, method.get());
- LoadMethod(dex_file, dex_method, klass, method);
- if (oat_class.get() != NULL) {
- LinkCode(method, oat_class.get(), method_index);
- }
+ for (size_t i = 0; it.HasNextVirtualMethod(); i++, it.Next()) {
+ SirtRef<Method> method(AllocMethod());
+ klass->SetVirtualMethod(i, method.get());
+ LoadMethod(dex_file, it, klass, method);
+ if (oat_class.get() != NULL) {
+ LinkCode(method, oat_class.get(), method_index);
}
+ method_index++;
}
+ DCHECK(!it.HasNext());
}
void ClassLinker::LoadInterfaces(const DexFile& dex_file,
@@ -1273,15 +1251,13 @@ void ClassLinker::LoadInterfaces(const DexFile& dex_file,
}
}
-void ClassLinker::LoadField(const DexFile& dex_file,
- const DexFile::Field& src,
- SirtRef<Class>& klass,
- SirtRef<Field>& dst) {
- const DexFile::FieldId& field_id = dex_file.GetFieldId(src.field_idx_);
+void ClassLinker::LoadField(const DexFile& dex_file, const ClassDataItemIterator& it,
+ SirtRef<Class>& klass, SirtRef<Field>& dst) {
+ const DexFile::FieldId& field_id = dex_file.GetFieldId(it.GetMemberIndex());
dst->SetDeclaringClass(klass.get());
dst->SetName(ResolveString(dex_file, field_id.name_idx_, klass->GetDexCache()));
dst->SetTypeIdx(field_id.type_idx_);
- dst->SetAccessFlags(src.access_flags_);
+ dst->SetAccessFlags(it.GetMemberAccessFlags());
// In order to access primitive types using GetTypeDuringLinking we need to
// ensure they are resolved into the dex cache
@@ -1293,11 +1269,9 @@ void ClassLinker::LoadField(const DexFile& dex_file,
}
}
-void ClassLinker::LoadMethod(const DexFile& dex_file,
- const DexFile::Method& src,
- SirtRef<Class>& klass,
- SirtRef<Method>& dst) {
- const DexFile::MethodId& method_id = dex_file.GetMethodId(src.method_idx_);
+void ClassLinker::LoadMethod(const DexFile& dex_file, const ClassDataItemIterator& it,
+ SirtRef<Class>& klass, SirtRef<Method>& dst) {
+ const DexFile::MethodId& method_id = dex_file.GetMethodId(it.GetMemberIndex());
dst->SetDeclaringClass(klass.get());
String* method_name = ResolveString(dex_file, method_id.name_idx_, klass->GetDexCache());
@@ -1310,7 +1284,7 @@ void ClassLinker::LoadMethod(const DexFile& dex_file,
}
int32_t utf16_length;
- std::string signature(dex_file.CreateMethodDescriptor(method_id.proto_idx_, &utf16_length));
+ std::string signature(dex_file.CreateMethodSignature(method_id.proto_idx_, &utf16_length));
String* signature_string = intern_table_->InternStrong(utf16_length, signature.c_str());
if (signature_string == NULL) {
return;
@@ -1333,14 +1307,14 @@ void ClassLinker::LoadMethod(const DexFile& dex_file,
}
dst->SetProtoIdx(method_id.proto_idx_);
- dst->SetCodeItemOffset(src.code_off_);
+ dst->SetCodeItemOffset(it.GetMethodCodeItemOffset());
const char* shorty = dex_file.GetShorty(method_id.proto_idx_);
String* shorty_string = intern_table_->InternStrong(shorty);
dst->SetShorty(shorty_string);
if (shorty_string == NULL) {
return;
}
- dst->SetAccessFlags(src.access_flags_);
+ dst->SetAccessFlags(it.GetMemberAccessFlags());
uint32_t return_type_idx = dex_file.GetProtoId(method_id.proto_idx_).return_type_idx_;
DCHECK_LT(return_type_idx, dex_file.NumTypeIds());
dst->SetReturnTypeIdx(return_type_idx);
@@ -1354,14 +1328,14 @@ void ClassLinker::LoadMethod(const DexFile& dex_file,
// TODO: check for finalize method
- const DexFile::CodeItem* code_item = dex_file.GetCodeItem(src);
+ const DexFile::CodeItem* code_item = it.GetMethodCodeItem();
if (code_item != NULL) {
dst->SetNumRegisters(code_item->registers_size_);
dst->SetNumIns(code_item->ins_size_);
dst->SetNumOuts(code_item->outs_size_);
} else {
uint16_t num_args = Method::NumArgRegisters(shorty);
- if ((src.access_flags_ & kAccStatic) != 0) {
+ if ((it.GetMemberAccessFlags() & kAccStatic) != 0) {
++num_args;
}
dst->SetNumRegisters(num_args);
@@ -1944,9 +1918,8 @@ bool ClassLinker::HasSameMethodDescriptorClasses(const Method* method,
}
const DexFile& dex_file = FindDexFile(method->GetDeclaringClass()->GetDexCache());
const DexFile::ProtoId& proto_id = dex_file.GetProtoId(method->GetProtoIdx());
- DexFile::ParameterIterator *it;
- for (it = dex_file.GetParameterIterator(proto_id); it->HasNext(); it->Next()) {
- const char* descriptor = it->GetDescriptor();
+ for (DexFileParameterIterator it(dex_file, proto_id); it.HasNext(); it.Next()) {
+ const char* descriptor = it.GetDescriptor();
if (descriptor == NULL) {
break;
}
@@ -2031,15 +2004,12 @@ bool ClassLinker::EnsureInitialized(Class* c, bool can_run_clinit) {
}
void ClassLinker::ConstructFieldMap(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def,
- Class* c, std::map<int, Field*>& field_map) {
+ Class* c, std::map<uint32_t, Field*>& field_map) {
const ClassLoader* cl = c->GetClassLoader();
const byte* class_data = dex_file.GetClassData(dex_class_def);
- DexFile::ClassDataHeader header = dex_file.ReadClassDataHeader(&class_data);
- uint32_t last_idx = 0;
- for (size_t i = 0; i < header.static_fields_size_; ++i) {
- DexFile::Field dex_field;
- dex_file.dexReadClassDataField(&class_data, &dex_field, &last_idx);
- field_map[i] = ResolveField(dex_file, dex_field.field_idx_, c->GetDexCache(), cl, true);
+ ClassDataItemIterator it(dex_file, class_data);
+ for (size_t i = 0; it.HasNextStaticField(); i++, it.Next()) {
+ field_map[i] = ResolveField(dex_file, it.GetMemberIndex(), c->GetDexCache(), cl, true);
}
}
@@ -2053,61 +2023,18 @@ void ClassLinker::InitializeStaticFields(Class* klass) {
if (dex_cache == NULL) {
return;
}
- const std::string descriptor(klass->GetDescriptor()->ToModifiedUtf8());
const DexFile& dex_file = FindDexFile(dex_cache);
+ const std::string descriptor(klass->GetDescriptor()->ToModifiedUtf8());
const DexFile::ClassDef* dex_class_def = dex_file.FindClassDef(descriptor);
CHECK(dex_class_def != NULL);
+ EncodedStaticFieldValueIterator it(dex_file, dex_cache, this, *dex_class_def);
- // We reordered the fields, so we need to be able to map the field indexes to the right fields.
- std::map<int, Field*> field_map;
- ConstructFieldMap(dex_file, *dex_class_def, klass, field_map);
-
- const byte* addr = dex_file.GetEncodedArray(*dex_class_def);
- if (addr == NULL) {
- // All this class' static fields have default values.
- return;
- }
- size_t array_size = DecodeUnsignedLeb128(&addr);
- for (size_t i = 0; i < array_size; ++i) {
- Field* field = field_map[i];
- JValue value;
- DexFile::ValueType type = dex_file.ReadEncodedValue(&addr, &value);
- switch (type) {
- case DexFile::kByte:
- field->SetByte(NULL, value.b);
- break;
- case DexFile::kShort:
- field->SetShort(NULL, value.s);
- break;
- case DexFile::kChar:
- field->SetChar(NULL, value.c);
- break;
- case DexFile::kInt:
- field->SetInt(NULL, value.i);
- break;
- case DexFile::kLong:
- field->SetLong(NULL, value.j);
- break;
- case DexFile::kFloat:
- field->SetFloat(NULL, value.f);
- break;
- case DexFile::kDouble:
- field->SetDouble(NULL, value.d);
- break;
- case DexFile::kString: {
- uint32_t string_idx = value.i;
- const String* resolved = ResolveString(dex_file, string_idx, klass->GetDexCache());
- field->SetObject(NULL, resolved);
- break;
- }
- case DexFile::kBoolean:
- field->SetBoolean(NULL, value.z);
- break;
- case DexFile::kNull:
- field->SetObject(NULL, value.l);
- break;
- default:
- LOG(FATAL) << "Unknown type " << static_cast<int>(type);
+ if (it.HasNext()) {
+ // We reordered the fields, so we need to be able to map the field indexes to the right fields.
+ std::map<uint32_t, Field*> field_map;
+ ConstructFieldMap(dex_file, *dex_class_def, klass, field_map);
+ for (size_t i = 0; it.HasNext(); i++, it.Next()) {
+ it.ReadValueToField(field_map[i]);
}
}
}
@@ -2135,7 +2062,7 @@ bool ClassLinker::LinkClass(SirtRef<Class>& klass) {
bool ClassLinker::LoadSuperAndInterfaces(SirtRef<Class>& klass, const DexFile& dex_file) {
CHECK_EQ(Class::kStatusIdx, klass->GetStatus());
- if (klass->GetSuperClassTypeIdx() != DexFile::kDexNoIndex) {
+ if (klass->GetSuperClassTypeIdx() != DexFile::kDexNoIndex16) {
Class* super_class = ResolveType(dex_file, klass->GetSuperClassTypeIdx(), klass.get());
if (super_class == NULL) {
DCHECK(Thread::Current()->IsExceptionPending());
@@ -2691,7 +2618,7 @@ Class* ClassLinker::ResolveType(const DexFile& dex_file,
const ClassLoader* class_loader) {
Class* resolved = dex_cache->GetResolvedType(type_idx);
if (resolved == NULL) {
- const char* descriptor = dex_file.dexStringByTypeIdx(type_idx);
+ const char* descriptor = dex_file.StringByTypeIdx(type_idx);
resolved = FindClass(descriptor, class_loader);
if (resolved != NULL) {
Class* check = resolved;
@@ -2731,8 +2658,8 @@ Method* ClassLinker::ResolveMethod(const DexFile& dex_file,
return NULL;
}
- const char* name = dex_file.dexStringById(method_id.name_idx_);
- std::string signature(dex_file.CreateMethodDescriptor(method_id.proto_idx_, NULL));
+ const char* name = dex_file.StringDataByIdx(method_id.name_idx_);
+ std::string signature(dex_file.CreateMethodSignature(method_id.proto_idx_, NULL));
if (is_direct) {
resolved = klass->FindDirectMethod(name, signature);
} else if (klass->IsInterface()) {
diff --git a/src/class_linker.h b/src/class_linker.h
index 03c8341d3a..478a26041e 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -282,7 +282,7 @@ class ClassLinker {
void AppendToBootClassPath(const DexFile& dex_file, SirtRef<DexCache>& dex_cache);
void ConstructFieldMap(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def,
- Class* c, std::map<int, Field*>& field_map);
+ Class* c, std::map<uint32_t, Field*>& field_map);
size_t SizeOfClass(const DexFile& dex_file,
const DexFile::ClassDef& dex_class_def);
@@ -296,15 +296,11 @@ class ClassLinker {
const DexFile::ClassDef& dex_class_def,
SirtRef<Class>& klass);
- void LoadField(const DexFile& dex_file,
- const DexFile::Field& dex_field,
- SirtRef<Class>& klass,
+ void LoadField(const DexFile& dex_file, const ClassDataItemIterator& it, SirtRef<Class>& klass,
SirtRef<Field>& dst);
- void LoadMethod(const DexFile& dex_file,
- const DexFile::Method& dex_method,
- SirtRef<Class>& klass,
- SirtRef<Method>& dst);
+ void LoadMethod(const DexFile& dex_file, const ClassDataItemIterator& dex_method,
+ SirtRef<Class>& klass, SirtRef<Method>& dst);
// Inserts a class into the class table. Returns true if the class
// was inserted.
diff --git a/src/common_test.h b/src/common_test.h
index 3966742017..56b54a3851 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -100,7 +100,9 @@ class CommonTest : public testing::Test {
void MakeExecutable(Method* method) {
CHECK(method != NULL);
- const CompiledInvokeStub* compiled_invoke_stub = compiler_->GetCompiledInvokeStub(method);
+ const CompiledInvokeStub* compiled_invoke_stub =
+ compiler_->FindInvokeStub(method->IsStatic(),
+ method->GetShorty()->ToModifiedUtf8().c_str());
CHECK(compiled_invoke_stub != NULL) << PrettyMethod(method);
const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode();
MakeExecutable(invoke_stub);
@@ -110,7 +112,11 @@ class CommonTest : public testing::Test {
<< " invoke_stub=" << reinterpret_cast<void*>(method_invoke_stub);
if (!method->IsAbstract()) {
- const CompiledMethod* compiled_method = compiler_->GetCompiledMethod(method);
+ const DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
+ const DexFile& dex_file = Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache);
+ const CompiledMethod* compiled_method =
+ compiler_->GetCompiledMethod(Compiler::MethodReference(&dex_file,
+ method->GetDexMethodIndex()));
CHECK(compiled_method != NULL) << PrettyMethod(method);
const std::vector<uint8_t>& code = compiled_method->GetCode();
MakeExecutable(code);
@@ -119,7 +125,6 @@ class CommonTest : public testing::Test {
LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " code=" << method_code;
OatFile::OatMethod oat_method(method_code,
compiled_method->GetFrameSizeInBytes(),
- compiled_method->GetReturnPcOffsetInBytes(),
compiled_method->GetCoreSpillMask(),
compiled_method->GetFpSpillMask(),
&compiled_method->GetMappingTable()[0],
@@ -134,7 +139,6 @@ class CommonTest : public testing::Test {
kStackAlignment,
0,
0,
- 0,
NULL,
NULL,
method_invoke_stub);
diff --git a/src/compiled_method.cc b/src/compiled_method.cc
index 082600f5ab..500a62bd82 100644
--- a/src/compiled_method.cc
+++ b/src/compiled_method.cc
@@ -7,7 +7,6 @@ namespace art {
CompiledMethod::CompiledMethod(InstructionSet instruction_set,
std::vector<short>& short_code,
const size_t frame_size_in_bytes,
- const size_t return_pc_offset_in_bytes,
const uint32_t core_spill_mask,
const uint32_t fp_spill_mask,
std::vector<uint32_t>& mapping_table,
@@ -37,7 +36,6 @@ CompiledMethod::CompiledMethod(InstructionSet instruction_set,
instruction_set_ = instruction_set;
code_ = byte_code;
frame_size_in_bytes_ = frame_size_in_bytes;
- return_pc_offset_in_bytes_ = return_pc_offset_in_bytes;
core_spill_mask_ = core_spill_mask;
fp_spill_mask_ = fp_spill_mask;
mapping_table_ = length_prefixed_mapping_table;
@@ -49,7 +47,6 @@ CompiledMethod::CompiledMethod(InstructionSet instruction_set,
CompiledMethod::CompiledMethod(InstructionSet instruction_set,
std::vector<uint8_t>& code,
const size_t frame_size_in_bytes,
- const size_t return_pc_offset_in_bytes,
const uint32_t core_spill_mask,
const uint32_t fp_spill_mask) {
CHECK_NE(code.size(), 0U);
@@ -57,7 +54,6 @@ CompiledMethod::CompiledMethod(InstructionSet instruction_set,
instruction_set_ = instruction_set;
code_ = code;
frame_size_in_bytes_ = frame_size_in_bytes;
- return_pc_offset_in_bytes_ = return_pc_offset_in_bytes;
core_spill_mask_ = core_spill_mask;
fp_spill_mask_ = fp_spill_mask;
}
@@ -76,10 +72,6 @@ size_t CompiledMethod::GetFrameSizeInBytes() const {
return frame_size_in_bytes_;
}
-size_t CompiledMethod::GetReturnPcOffsetInBytes() const {
- return return_pc_offset_in_bytes_;
-}
-
uint32_t CompiledMethod::GetCoreSpillMask() const {
return core_spill_mask_;
}
@@ -146,7 +138,6 @@ const void* CompiledMethod::CodePointer(const void* code_pointer,
}
}
-
CompiledInvokeStub::CompiledInvokeStub(std::vector<uint8_t>& code) {
CHECK_NE(code.size(), 0U);
code_ = code;
diff --git a/src/compiled_method.h b/src/compiled_method.h
index 1a5c34dc17..4e0870bbc0 100644
--- a/src/compiled_method.h
+++ b/src/compiled_method.h
@@ -16,7 +16,6 @@ class CompiledMethod {
CompiledMethod(InstructionSet instruction_set,
std::vector<short>& code,
const size_t frame_size_in_bytes,
- const size_t return_pc_offset_in_bytes,
const uint32_t core_spill_mask,
const uint32_t fp_spill_mask,
std::vector<uint32_t>& mapping_table,
@@ -26,7 +25,6 @@ class CompiledMethod {
CompiledMethod(InstructionSet instruction_set,
std::vector<uint8_t>& code,
const size_t frame_size_in_bytes,
- const size_t return_pc_offset_in_bytes,
const uint32_t core_spill_mask,
const uint32_t fp_spill_mask);
@@ -35,12 +33,10 @@ class CompiledMethod {
InstructionSet GetInstructionSet() const;
const std::vector<uint8_t>& GetCode() const;
size_t GetFrameSizeInBytes() const;
- size_t GetReturnPcOffsetInBytes() const;
uint32_t GetCoreSpillMask() const;
uint32_t GetFpSpillMask() const;
const std::vector<uint32_t>& GetMappingTable() const;
const std::vector<uint16_t>& GetVmapTable() const;
-
// Aligns an offset from a page aligned value to make it suitable
// for code storage. important to ensure that PC relative value
// computations work out as expected on ARM.
@@ -61,7 +57,6 @@ class CompiledMethod {
InstructionSet instruction_set_;
std::vector<uint8_t> code_;
size_t frame_size_in_bytes_;
- size_t return_pc_offset_in_bytes_;
uint32_t core_spill_mask_;
uint32_t fp_spill_mask_;
std::vector<uint32_t> mapping_table_;
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);
diff --git a/src/compiler.h b/src/compiler.h
index 55bab59e6b..f29fbbc94a 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -12,6 +12,8 @@
#include "runtime.h"
#include "unordered_map.h"
+#include <string>
+
namespace art {
class Compiler {
@@ -52,8 +54,11 @@ class Compiler {
static ByteArray* CreateResolutionStub(InstructionSet instruction_set,
Runtime::TrampolineType type);
- const CompiledMethod* GetCompiledMethod(const Method* method) const;
- const CompiledInvokeStub* GetCompiledInvokeStub(const Method* method) const;
+ // A method is uniquely located by its DexFile and index into the method_id table of that dex file
+ typedef std::pair<const DexFile*, uint32_t> MethodReference;
+
+ CompiledMethod* GetCompiledMethod(MethodReference ref) const;
+ const CompiledInvokeStub* FindInvokeStub(bool is_static, const char* shorty) const;
// Callbacks from OAT/ART compiler to see what runtime checks must be generated
bool CanAssumeTypeIsPresentInDexCache(const Method* referrer, uint32_t type_idx) const {
@@ -70,6 +75,7 @@ class Compiler {
DCHECK(resolved_class == NULL || referrer->GetDeclaringClass()->CanAccess(resolved_class));
return resolved_class != NULL;
}
+
private:
// Attempt to resolve all type, methods, fields, and strings
// referenced from code in the dex file following PathClassLoader
@@ -85,21 +91,41 @@ class Compiler {
void Compile(const ClassLoader* class_loader);
void CompileDexFile(const ClassLoader* class_loader, const DexFile& dex_file);
- void CompileClass(const Class* klass);
- void CompileMethod(const Method* method);
+ void CompileClass(const DexFile::ClassDef& class_def, const ClassLoader* class_loader,
+ const DexFile& dex_file);
+ void 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);
// After compiling, walk all the DexCaches and set the code and
// method pointers of CodeAndDirectMethods entries in the DexCaches.
void SetCodeAndDirectMethods(const ClassLoader* class_loader);
void SetCodeAndDirectMethodsDexFile(const DexFile& dex_file);
+ void InsertInvokeStub(bool is_static, const char* shorty,
+ const CompiledInvokeStub* compiled_invoke_stub);
+
InstructionSet instruction_set_;
JniCompiler jni_compiler_;
- typedef std::tr1::unordered_map<const Method*, CompiledMethod*, ObjectIdentityHash> MethodTable;
+ struct MethodReferenceHash {
+ size_t operator()(const MethodReference id) const {
+ size_t dex = reinterpret_cast<size_t>(id.first);
+ DCHECK_NE(dex, static_cast<size_t>(0));
+ dex += 33; // dex is an aligned pointer, get some non-zero low bits
+ size_t idx = id.second;
+ if (idx == 0) { // special case of a method index of 0
+ return dex * 5381;
+ } else {
+ return dex * idx;
+ }
+ }
+ };
+ typedef std::tr1::unordered_map<const MethodReference, CompiledMethod*, MethodReferenceHash> MethodTable;
+ // All method references that this compiler has compiled
MethodTable compiled_methods_;
- typedef std::tr1::unordered_map<const Method*, CompiledInvokeStub*, ObjectIdentityHash> InvokeStubTable;
+ typedef std::tr1::unordered_map<std::string, const CompiledInvokeStub*> InvokeStubTable;
+ // Invocation stubs created to allow invocation of the compiled methods
InvokeStubTable compiled_invoke_stubs_;
bool image_;
diff --git a/src/compiler/Compiler.h b/src/compiler/Compiler.h
index 28a689fb4b..917e3fda03 100644
--- a/src/compiler/Compiler.h
+++ b/src/compiler/Compiler.h
@@ -17,6 +17,8 @@
#ifndef ART_SRC_COMPILER_COMPILER_H_
#define ART_SRC_COMPILER_COMPILER_H_
+#include "dex_file.h"
+
#define COMPILER_TRACED(X)
#define COMPILER_TRACEE(X)
@@ -99,9 +101,9 @@ bool oatArchInit(void);
void oatArchDump(void);
bool oatStartup(void);
void oatShutdown(void);
-CompiledMethod* oatCompileMethod(const Compiler& compiler,
- const Method* method,
- OatInstructionSetType);
+CompiledMethod* oatCompileMethod(const Compiler& compiler, bool is_direct,
+ uint32_t method_idx, const art::ClassLoader* class_loader,
+ const art::DexFile& dex_file, OatInstructionSetType);
void oatDumpStats(void);
void oatScanAllClassPointers(void (*callback)(void* ptr));
void oatInitializeSSAConversion(struct CompilationUnit* cUnit);
diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc
index d4f1b27b4b..9a2cc31079 100644
--- a/src/compiler/Frontend.cc
+++ b/src/compiler/Frontend.cc
@@ -18,6 +18,7 @@
#include "CompilerInternals.h"
#include "Dataflow.h"
#include "constants.h"
+#include "leb128.h"
#include "object.h"
#include "runtime.h"
@@ -432,7 +433,7 @@ STATIC void processTryCatchBlocks(CompilationUnit* cUnit)
for (int i = 0; i < triesSize; i++) {
const art::DexFile::TryItem* pTry =
- art::DexFile::dexGetTryItems(*code_item, i);
+ art::DexFile::GetTryItems(*code_item, i);
int startOffset = pTry->start_addr_;
int endOffset = startOffset + pTry->insn_count_;
for (offset = startOffset; offset < endOffset; offset++) {
@@ -442,16 +443,15 @@ STATIC void processTryCatchBlocks(CompilationUnit* cUnit)
// Iterate over each of the handlers to enqueue the empty Catch blocks
const art::byte* handlers_ptr =
- art::DexFile::dexGetCatchHandlerData(*code_item, 0);
+ art::DexFile::GetCatchHandlerData(*code_item, 0);
uint32_t handlers_size = art::DecodeUnsignedLeb128(&handlers_ptr);
for (uint32_t idx = 0; idx < handlers_size; idx++) {
- art::DexFile::CatchHandlerIterator iterator(handlers_ptr);
-
- for (; !iterator.HasNext(); iterator.Next()) {
- uint32_t address = iterator.Get().address_;
+ art::CatchHandlerIterator iterator(handlers_ptr);
+ for (; iterator.HasNext(); iterator.Next()) {
+ uint32_t address = iterator.GetHandlerAddress();
findBlock(cUnit, address, false /* split */, true /*create*/);
}
- handlers_ptr = iterator.GetData();
+ handlers_ptr = iterator.EndDataPointer();
}
}
@@ -625,8 +625,7 @@ STATIC void processCanThrow(CompilationUnit* cUnit, BasicBlock* curBlock,
/* In try block */
if (oatIsBitSet(tryBlockAddr, curOffset)) {
- art::DexFile::CatchHandlerIterator iterator =
- art::DexFile::dexFindCatchHandler(*code_item, curOffset);
+ art::CatchHandlerIterator iterator(*code_item, curOffset);
if (curBlock->successorBlockList.blockListType != kNotUsed) {
LOG(FATAL) << "Successor block list already in use: " <<
@@ -636,8 +635,8 @@ STATIC void processCanThrow(CompilationUnit* cUnit, BasicBlock* curBlock,
curBlock->successorBlockList.blockListType = kCatch;
oatInitGrowableList(&curBlock->successorBlockList.blocks, 2);
- for (;!iterator.HasNext(); iterator.Next()) {
- BasicBlock *catchBlock = findBlock(cUnit, iterator.Get().address_,
+ for (;iterator.HasNext(); iterator.Next()) {
+ BasicBlock *catchBlock = findBlock(cUnit, iterator.GetHandlerAddress(),
false /* split*/,
false /* creat */);
catchBlock->catchEntry = true;
@@ -645,7 +644,7 @@ STATIC void processCanThrow(CompilationUnit* cUnit, BasicBlock* curBlock,
(SuccessorBlockInfo *) oatNew(sizeof(SuccessorBlockInfo),
false);
successorBlockInfo->block = catchBlock;
- successorBlockInfo->key = iterator.Get().type_idx_;
+ successorBlockInfo->key = iterator.GetHandlerTypeIndex();
oatInsertGrowableList(&curBlock->successorBlockList.blocks,
(intptr_t) successorBlockInfo);
oatSetBit(catchBlock->predecessors, curBlock->id);
@@ -692,16 +691,26 @@ STATIC void processCanThrow(CompilationUnit* cUnit, BasicBlock* curBlock,
/*
* Compile a method.
*/
-CompiledMethod* oatCompileMethod(const Compiler& compiler, const Method* method, art::InstructionSet insnSet)
+CompiledMethod* oatCompileMethod(const Compiler& compiler, bool is_direct,
+ uint32_t method_idx, const art::ClassLoader* class_loader,
+ const art::DexFile& dex_file, art::InstructionSet insnSet)
{
+ art::ClassLinker* linker = art::Runtime::Current()->GetClassLinker();
+ art::DexCache* dex_cache = linker->FindDexCache(dex_file);
+ art::Method* method = linker->ResolveMethod(dex_file, method_idx, dex_cache,
+ class_loader, is_direct);
+ if (method == NULL) {
+ CHECK(Thread::Current()->IsExceptionPending());
+ Thread::Current()->ClearException();
+ LOG(INFO) << "Couldn't resolve " << PrettyMethod(method_idx, dex_file, true)
+ << " for compilation";
+ return NULL;
+ }
if (compiler.IsVerbose()) {
LOG(INFO) << "Compiling " << PrettyMethod(method) << "...";
}
oatArenaReset();
- art::ClassLinker* class_linker = art::Runtime::Current()->GetClassLinker();
- const art::DexFile& dex_file = class_linker->FindDexFile(
- method->GetDeclaringClass()->GetDexCache());
const art::DexFile::CodeItem* code_item =
dex_file.GetCodeItem(method->GetCodeItemOffset());
const u2* codePtr = code_item->insns_;
@@ -907,9 +916,10 @@ CompiledMethod* oatCompileMethod(const Compiler& compiler, const Method* method,
+ __builtin_popcount(cUnit->fpSpillMask)));
DCHECK_GE(vmapTable.size(), 1U); // should always at least one INVALID_VREG for lr
- CompiledMethod* result = new CompiledMethod(art::kThumb2,
- cUnit->codeBuffer, cUnit->frameSize, cUnit->frameSize - sizeof(intptr_t),
- cUnit->coreSpillMask, cUnit->fpSpillMask, cUnit->mappingTable, vmapTable);
+ CompiledMethod* result = new CompiledMethod(art::kThumb2, cUnit->codeBuffer,
+ cUnit->frameSize, cUnit->coreSpillMask,
+ cUnit->fpSpillMask, cUnit->mappingTable,
+ vmapTable);
if (compiler.IsVerbose()) {
LOG(INFO) << "Compiled " << PrettyMethod(method)
diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc
index bff53beb06..006be694bd 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -39,8 +39,8 @@ std::string fieldNameFromIndex(const Method* method, uint32_t fieldIdx)
const art::DexFile& dex_file = class_linker->FindDexFile(
method->GetDeclaringClass()->GetDexCache());
const art::DexFile::FieldId& field_id = dex_file.GetFieldId(fieldIdx);
- std::string class_name = dex_file.dexStringByTypeIdx(field_id.class_idx_);
- std::string field_name = dex_file.dexStringById(field_id.name_idx_);
+ std::string class_name = dex_file.StringByTypeIdx(field_id.class_idx_);
+ std::string field_name = dex_file.StringDataByIdx(field_id.name_idx_);
return class_name + "." + field_name;
}
diff --git a/src/dex_cache.cc b/src/dex_cache.cc
index 4eb18a565b..c43f5bf573 100644
--- a/src/dex_cache.cc
+++ b/src/dex_cache.cc
@@ -9,6 +9,14 @@
namespace art {
+void CodeAndDirectMethods::SetResolvedDirectMethod(uint32_t method_idx, Method* method) {
+ CHECK(method != NULL);
+ CHECK(method->IsDirect()) << PrettyMethod(method);
+ CHECK(method->GetCode() != NULL) << PrettyMethod(method);
+ Set(CodeIndex(method_idx), reinterpret_cast<int32_t>(method->GetCode()));
+ Set(MethodIndex(method_idx), reinterpret_cast<int32_t>(method));
+}
+
void DexCache::Init(String* location,
ObjectArray<String>* strings,
ObjectArray<Class>* resolved_types,
diff --git a/src/dex_cache.h b/src/dex_cache.h
index ee1731a8de..8cd9b1202f 100644
--- a/src/dex_cache.h
+++ b/src/dex_cache.h
@@ -33,13 +33,7 @@ class MANAGED CodeAndDirectMethods : public IntArray {
Set(MethodIndex(method_idx), method_idx);
}
- void SetResolvedDirectMethod(uint32_t method_idx, Method* method) {
- CHECK(method != NULL);
- CHECK(method->IsDirect()) << PrettyMethod(method);
- CHECK(method->GetCode() != NULL) << PrettyMethod(method);
- Set(CodeIndex(method_idx), reinterpret_cast<int32_t>(method->GetCode()));
- Set(MethodIndex(method_idx), reinterpret_cast<int32_t>(method));
- }
+ void SetResolvedDirectMethod(uint32_t method_idx, Method* method);
static size_t LengthAsArray(size_t elements) {
return kMax * elements;
diff --git a/src/dex_file.cc b/src/dex_file.cc
index 21489dd2f5..e9a883c9e3 100644
--- a/src/dex_file.cc
+++ b/src/dex_file.cc
@@ -14,12 +14,15 @@
#include <map>
#include "UniquePtr.h"
+#include "class_linker.h"
#include "globals.h"
+#include "leb128.h"
#include "logging.h"
#include "object.h"
#include "os.h"
#include "stringprintf.h"
#include "thread.h"
+#include "utf.h"
#include "utils.h"
#include "zip_archive.h"
@@ -421,6 +424,19 @@ uint32_t DexFile::GetVersion() const {
return atoi(version);
}
+int32_t DexFile::GetStringLength(const StringId& string_id) const {
+ const byte* ptr = base_ + string_id.string_data_off_;
+ return DecodeUnsignedLeb128(&ptr);
+}
+
+// Returns a pointer to the UTF-8 string data referred to by the given string_id.
+const char* DexFile::GetStringDataAndLength(const StringId& string_id, int32_t* length) const {
+ CHECK(length != NULL);
+ const byte* ptr = base_ + string_id.string_data_off_;
+ *length = DecodeUnsignedLeb128(&ptr);
+ return reinterpret_cast<const char*>(ptr);
+}
+
void DexFile::InitIndex() {
CHECK_EQ(index_.size(), 0U);
for (size_t i = 0; i < NumClassDefs(); ++i) {
@@ -447,11 +463,172 @@ const DexFile::ClassDef* DexFile::FindClassDef(const StringPiece& descriptor) co
return NULL;
}
+const DexFile::MethodId* DexFile::FindMethodId(const DexFile::TypeId& klass,
+ const DexFile::StringId& name,
+ const DexFile::ProtoId& signature) const {
+ // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx
+ const uint16_t class_idx = GetIndexForTypeId(klass);
+ const uint32_t name_idx = GetIndexForStringId(name);
+ const uint16_t proto_idx = GetIndexForProtoId(signature);
+ uint32_t lo = 0;
+ uint32_t hi = NumMethodIds() - 1;
+ while (hi >= lo) {
+ uint32_t mid = (hi + lo) / 2;
+ const DexFile::MethodId& method = GetMethodId(mid);
+ if (class_idx > method.class_idx_) {
+ lo = mid + 1;
+ } else if (class_idx < method.class_idx_) {
+ hi = mid - 1;
+ } else {
+ if (name_idx > method.name_idx_) {
+ lo = mid + 1;
+ } else if (name_idx < method.name_idx_) {
+ hi = mid - 1;
+ } else {
+ if (proto_idx > method.proto_idx_) {
+ lo = mid + 1;
+ } else if (proto_idx < method.proto_idx_) {
+ hi = mid - 1;
+ } else {
+ return &method;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+const DexFile::StringId* DexFile::FindStringId(const std::string& string) const {
+ uint32_t lo = 0;
+ uint32_t hi = NumStringIds() - 1;
+ while (hi >= lo) {
+ uint32_t mid = (hi + lo) / 2;
+ int32_t length;
+ const DexFile::StringId& str_id = GetStringId(mid);
+ const char* str = GetStringDataAndLength(str_id, &length);
+ int compare = CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(string.c_str(), str);
+ if (compare > 0) {
+ lo = mid + 1;
+ } else if (compare < 0) {
+ hi = mid - 1;
+ } else {
+ return &str_id;
+ }
+ }
+ return NULL;
+}
+
+const DexFile::TypeId* DexFile::FindTypeId(uint32_t string_idx) const {
+ uint32_t lo = 0;
+ uint32_t hi = NumTypeIds() - 1;
+ while (hi >= lo) {
+ uint32_t mid = (hi + lo) / 2;
+ const TypeId& type_id = GetTypeId(mid);
+ if (string_idx > type_id.descriptor_idx_) {
+ lo = mid + 1;
+ } else if (string_idx < type_id.descriptor_idx_) {
+ hi = mid - 1;
+ } else {
+ return &type_id;
+ }
+ }
+ return NULL;
+}
+
+const DexFile::ProtoId* DexFile::FindProtoId(uint16_t return_type_idx,
+ const std::vector<uint16_t>& signature_type_ids) const {
+ uint32_t lo = 0;
+ uint32_t hi = NumProtoIds() - 1;
+ while (hi >= lo) {
+ uint32_t mid = (hi + lo) / 2;
+ const DexFile::ProtoId& proto = GetProtoId(mid);
+ int compare = return_type_idx - proto.return_type_idx_;
+ if (compare == 0) {
+ DexFileParameterIterator it(*this, proto);
+ size_t i = 0;
+ while (it.HasNext() && i < signature_type_ids.size() && compare == 0) {
+ compare = signature_type_ids[i] - it.GetTypeId();
+ it.Next();
+ i++;
+ }
+ if (compare == 0) {
+ if (it.HasNext()) {
+ compare = -1;
+ } else if (i < signature_type_ids.size()) {
+ compare = 1;
+ }
+ }
+ }
+ if (compare > 0) {
+ lo = mid + 1;
+ } else if (compare < 0) {
+ hi = mid - 1;
+ } else {
+ return &proto;
+ }
+ }
+ return NULL;
+}
+
+// Given a signature place the type ids into the given vector
+bool DexFile::CreateTypeList(uint16_t* return_type_idx, std::vector<uint16_t>* param_type_idxs,
+ const std::string& signature) const {
+ if (signature[0] != '(') {
+ return false;
+ }
+ size_t offset = 1;
+ size_t end = signature.size();
+ bool process_return = false;
+ while (offset < end) {
+ char c = signature[offset];
+ offset++;
+ if (c == ')') {
+ process_return = true;
+ continue;
+ }
+ std::string descriptor;
+ descriptor += c;
+ while (c == '[') { // process array prefix
+ if (offset >= end) { // expect some descriptor following [
+ return false;
+ }
+ c = signature[offset];
+ offset++;
+ descriptor += c;
+ }
+ if (c == 'L') { // process type descriptors
+ do {
+ if (offset >= end) { // unexpected early termination of descriptor
+ return false;
+ }
+ c = signature[offset];
+ offset++;
+ descriptor += c;
+ } while (c != ';');
+ }
+ const DexFile::StringId* string_id = FindStringId(descriptor);
+ if (string_id == NULL) {
+ return false;
+ }
+ const DexFile::TypeId* type_id = FindTypeId(GetIndexForStringId(*string_id));
+ if (type_id == NULL) {
+ return false;
+ }
+ uint16_t type_idx = GetIndexForTypeId(*type_id);
+ if (!process_return) {
+ param_type_idxs->push_back(type_idx);
+ } else {
+ *return_type_idx = type_idx;
+ return offset == end; // return true if the signature had reached a sensible end
+ }
+ }
+ return false; // failed to correctly parse return type
+}
+
// Materializes the method descriptor for a method prototype. Method
// descriptors are not stored directly in the dex file. Instead, one
// must assemble the descriptor from references in the prototype.
-std::string DexFile::CreateMethodDescriptor(uint32_t proto_idx,
- int32_t* unicode_length) const {
+std::string DexFile::CreateMethodSignature(uint32_t proto_idx, int32_t* unicode_length) const {
const ProtoId& proto_id = GetProtoId(proto_idx);
std::string descriptor;
descriptor.push_back('(');
@@ -463,7 +640,7 @@ std::string DexFile::CreateMethodDescriptor(uint32_t proto_idx,
const TypeItem& type_item = type_list->GetTypeItem(i);
uint32_t type_idx = type_item.type_idx_;
int32_t type_length;
- const char* name = dexStringByTypeIdx(type_idx, &type_length);
+ const char* name = StringByTypeIdx(type_idx, &type_length);
parameter_length += type_length;
descriptor.append(name);
}
@@ -471,7 +648,7 @@ std::string DexFile::CreateMethodDescriptor(uint32_t proto_idx,
descriptor.push_back(')');
uint32_t return_type_idx = proto_id.return_type_idx_;
int32_t return_type_length;
- const char* name = dexStringByTypeIdx(return_type_idx, &return_type_length);
+ const char* name = StringByTypeIdx(return_type_idx, &return_type_length);
descriptor.append(name);
if (unicode_length != NULL) {
*unicode_length = parameter_length + return_type_length + 2; // 2 for ( and )
@@ -479,127 +656,6 @@ std::string DexFile::CreateMethodDescriptor(uint32_t proto_idx,
return descriptor;
}
-// Read a signed integer. "zwidth" is the zero-based byte count.
-static int32_t ReadSignedInt(const byte* ptr, int zwidth)
-{
- int32_t val = 0;
- for (int i = zwidth; i >= 0; --i) {
- val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24);
- }
- val >>= (3 - zwidth) * 8;
- return val;
-}
-
-// Read an unsigned integer. "zwidth" is the zero-based byte count,
-// "fill_on_right" indicates which side we want to zero-fill from.
-static uint32_t ReadUnsignedInt(const byte* ptr, int zwidth,
- bool fill_on_right) {
- uint32_t val = 0;
- if (!fill_on_right) {
- for (int i = zwidth; i >= 0; --i) {
- val = (val >> 8) | (((uint32_t)*ptr++) << 24);
- }
- val >>= (3 - zwidth) * 8;
- } else {
- for (int i = zwidth; i >= 0; --i) {
- val = (val >> 8) | (((uint32_t)*ptr++) << 24);
- }
- }
- return val;
-}
-
-// Read a signed long. "zwidth" is the zero-based byte count.
-static int64_t ReadSignedLong(const byte* ptr, int zwidth) {
- int64_t val = 0;
- for (int i = zwidth; i >= 0; --i) {
- val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56);
- }
- val >>= (7 - zwidth) * 8;
- return val;
-}
-
-// Read an unsigned long. "zwidth" is the zero-based byte count,
-// "fill_on_right" indicates which side we want to zero-fill from.
-static uint64_t ReadUnsignedLong(const byte* ptr, int zwidth,
- bool fill_on_right) {
- uint64_t val = 0;
- if (!fill_on_right) {
- for (int i = zwidth; i >= 0; --i) {
- val = (val >> 8) | (((uint64_t)*ptr++) << 56);
- }
- val >>= (7 - zwidth) * 8;
- } else {
- for (int i = zwidth; i >= 0; --i) {
- val = (val >> 8) | (((uint64_t)*ptr++) << 56);
- }
- }
- return val;
-}
-
-DexFile::ValueType DexFile::ReadEncodedValue(const byte** stream,
- JValue* value) const {
- const byte* ptr = *stream;
- byte value_type = *ptr++;
- byte value_arg = value_type >> kEncodedValueArgShift;
- size_t width = value_arg + 1; // assume and correct later
- int type = value_type & kEncodedValueTypeMask;
- switch (type) {
- case DexFile::kByte: {
- int32_t b = ReadSignedInt(ptr, value_arg);
- CHECK(IsInt(8, b));
- value->i = b;
- break;
- }
- case DexFile::kShort: {
- int32_t s = ReadSignedInt(ptr, value_arg);
- CHECK(IsInt(16, s));
- value->i = s;
- break;
- }
- case DexFile::kChar: {
- uint32_t c = ReadUnsignedInt(ptr, value_arg, false);
- CHECK(IsUint(16, c));
- value->i = c;
- break;
- }
- case DexFile::kInt:
- value->i = ReadSignedInt(ptr, value_arg);
- break;
- case DexFile::kLong:
- value->j = ReadSignedLong(ptr, value_arg);
- break;
- case DexFile::kFloat:
- value->i = ReadUnsignedInt(ptr, value_arg, true);
- break;
- case DexFile::kDouble:
- value->j = ReadUnsignedLong(ptr, value_arg, true);
- break;
- case DexFile::kBoolean:
- value->i = (value_arg != 0);
- width = 0;
- break;
- case DexFile::kString:
- case DexFile::kType:
- case DexFile::kMethod:
- case DexFile::kEnum:
- value->i = ReadUnsignedInt(ptr, value_arg, false);
- break;
- case DexFile::kField:
- case DexFile::kArray:
- case DexFile::kAnnotation:
- UNIMPLEMENTED(FATAL) << ": type " << type;
- break;
- case DexFile::kNull:
- value->i = 0;
- width = 0;
- break;
- default:
- LOG(FATAL) << "Unreached";
- }
- ptr += width;
- *stream = ptr;
- return static_cast<ValueType>(type);
-}
int32_t DexFile::GetLineNumFromPC(const art::Method* method, uint32_t rel_pc) const {
// For native method, lineno should be -2 to indicate it is native. Note that
@@ -613,13 +669,38 @@ int32_t DexFile::GetLineNumFromPC(const art::Method* method, uint32_t rel_pc) co
// A method with no line number info should return -1
LineNumFromPcContext context(rel_pc, -1);
- dexDecodeDebugInfo(code_item, method, LineNumForPcCb, NULL, &context);
+ DecodeDebugInfo(code_item, method, LineNumForPcCb, NULL, &context);
return context.line_num_;
}
-void DexFile::dexDecodeDebugInfo0(const CodeItem* code_item, const art::Method* method,
- DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
- void* cnxt, const byte* stream, LocalInfo* local_in_reg) const {
+int32_t DexFile::FindCatchHandlerOffset(const CodeItem &code_item, int32_t tries_size,
+ uint32_t address){
+ // Note: Signed type is important for max and min.
+ int32_t min = 0;
+ int32_t max = tries_size - 1;
+
+ while (max >= min) {
+ int32_t mid = (min + max) / 2;
+ const TryItem* pTry = DexFile::GetTryItems(code_item, mid);
+ uint32_t start = pTry->start_addr_;
+ if (address < start) {
+ max = mid - 1;
+ } else {
+ uint32_t end = start + pTry->insn_count_;
+ if (address >= end) {
+ min = mid + 1;
+ } else { // We have a winner!
+ return (int32_t) pTry->handler_off_;
+ }
+ }
+ }
+ // No match.
+ return -1;
+}
+
+void DexFile::DecodeDebugInfo0(const CodeItem* code_item, const Method* method,
+ DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
+ void* cnxt, const byte* stream, LocalInfo* local_in_reg) const {
uint32_t line = DecodeUnsignedLeb128(&stream);
uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
uint16_t arg_reg = code_item->registers_size_ - code_item->ins_size_;
@@ -639,17 +720,17 @@ void DexFile::dexDecodeDebugInfo0(const CodeItem* code_item, const art::Method*
arg_reg++;
}
- ParameterIterator* it = GetParameterIterator(GetProtoId(method->GetProtoIdx()));
- for (uint32_t i = 0; i < parameters_size && it->HasNext(); ++i, it->Next()) {
+ DexFileParameterIterator it(*this, GetProtoId(method->GetProtoIdx()));
+ for (uint32_t i = 0; i < parameters_size && it.HasNext(); ++i, it.Next()) {
if (arg_reg >= code_item->registers_size_) {
LOG(ERROR) << "invalid stream - arg reg >= reg size (" << arg_reg
<< " >= " << code_item->registers_size_ << ")";
return;
}
int32_t id = DecodeUnsignedLeb128P1(&stream);
- const char* descriptor = it->GetDescriptor();
+ const char* descriptor = it.GetDescriptor();
if (need_locals) {
- const char* name = dexStringById(id);
+ const char* name = StringDataByIdx(id);
local_in_reg[arg_reg].name_ = name;
local_in_reg[arg_reg].descriptor_ = descriptor;
local_in_reg[arg_reg].start_address_ = address;
@@ -666,7 +747,7 @@ void DexFile::dexDecodeDebugInfo0(const CodeItem* code_item, const art::Method*
}
}
- if (it->HasNext()) {
+ if (it.HasNext()) {
LOG(ERROR) << "invalid stream - problem with parameter iterator";
return;
}
@@ -709,10 +790,10 @@ void DexFile::dexDecodeDebugInfo0(const CodeItem* code_item, const art::Method*
if (need_locals) {
InvokeLocalCbIfLive(cnxt, reg, address, local_in_reg, local_cb);
- local_in_reg[reg].name_ = dexStringById(name_idx);
- local_in_reg[reg].descriptor_ = dexStringByTypeIdx(descriptor_idx);
+ local_in_reg[reg].name_ = StringDataByIdx(name_idx);
+ local_in_reg[reg].descriptor_ = StringByTypeIdx(descriptor_idx);
if (opcode == DBG_START_LOCAL_EXTENDED) {
- local_in_reg[reg].signature_ = dexStringById(signature_idx);
+ local_in_reg[reg].signature_ = StringDataByIdx(signature_idx);
}
local_in_reg[reg].start_address_ = address;
local_in_reg[reg].is_live_ = true;
@@ -779,4 +860,270 @@ void DexFile::dexDecodeDebugInfo0(const CodeItem* code_item, const art::Method*
}
}
+void DexFile::DecodeDebugInfo(const CodeItem* code_item, const art::Method* method,
+ DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
+ void* cnxt) const {
+ const byte* stream = GetDebugInfoStream(code_item);
+ LocalInfo local_in_reg[code_item->registers_size_];
+
+ if (stream != NULL) {
+ DecodeDebugInfo0(code_item, method, posCb, local_cb, cnxt, stream, local_in_reg);
+ }
+ for (int reg = 0; reg < code_item->registers_size_; reg++) {
+ InvokeLocalCbIfLive(cnxt, reg, code_item->insns_size_in_code_units_, local_in_reg, local_cb);
+ }
+}
+
+bool DexFile::LineNumForPcCb(void* cnxt, uint32_t address, uint32_t line_num) {
+ LineNumFromPcContext* context = (LineNumFromPcContext*) cnxt;
+
+ // We know that this callback will be called in
+ // ascending address order, so keep going until we find
+ // a match or we've just gone past it.
+ if (address > context->address_) {
+ // The line number from the previous positions callback
+ // wil be the final result.
+ return true;
+ } else {
+ context->line_num_ = line_num;
+ return address == context->address_;
+ }
+}
+
+// Decodes the header section from the class data bytes.
+void ClassDataItemIterator::ReadClassDataHeader() {
+ CHECK(ptr_pos_ != NULL);
+ header_.static_fields_size_ = DecodeUnsignedLeb128(&ptr_pos_);
+ header_.instance_fields_size_ = DecodeUnsignedLeb128(&ptr_pos_);
+ header_.direct_methods_size_ = DecodeUnsignedLeb128(&ptr_pos_);
+ header_.virtual_methods_size_ = DecodeUnsignedLeb128(&ptr_pos_);
+}
+
+void ClassDataItemIterator::ReadClassDataField() {
+ field_.field_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_);
+ field_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
+}
+
+void ClassDataItemIterator::ReadClassDataMethod() {
+ method_.method_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_);
+ method_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
+ method_.code_off_ = DecodeUnsignedLeb128(&ptr_pos_);
+}
+
+// Read a signed integer. "zwidth" is the zero-based byte count.
+static int32_t ReadSignedInt(const byte* ptr, int zwidth) {
+ int32_t val = 0;
+ for (int i = zwidth; i >= 0; --i) {
+ val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24);
+ }
+ val >>= (3 - zwidth) * 8;
+ return val;
+}
+
+// Read an unsigned integer. "zwidth" is the zero-based byte count,
+// "fill_on_right" indicates which side we want to zero-fill from.
+static uint32_t ReadUnsignedInt(const byte* ptr, int zwidth, bool fill_on_right) {
+ uint32_t val = 0;
+ if (!fill_on_right) {
+ for (int i = zwidth; i >= 0; --i) {
+ val = (val >> 8) | (((uint32_t)*ptr++) << 24);
+ }
+ val >>= (3 - zwidth) * 8;
+ } else {
+ for (int i = zwidth; i >= 0; --i) {
+ val = (val >> 8) | (((uint32_t)*ptr++) << 24);
+ }
+ }
+ return val;
+}
+
+// Read a signed long. "zwidth" is the zero-based byte count.
+static int64_t ReadSignedLong(const byte* ptr, int zwidth) {
+ int64_t val = 0;
+ for (int i = zwidth; i >= 0; --i) {
+ val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56);
+ }
+ val >>= (7 - zwidth) * 8;
+ return val;
+}
+
+// Read an unsigned long. "zwidth" is the zero-based byte count,
+// "fill_on_right" indicates which side we want to zero-fill from.
+static uint64_t ReadUnsignedLong(const byte* ptr, int zwidth, bool fill_on_right) {
+ uint64_t val = 0;
+ if (!fill_on_right) {
+ for (int i = zwidth; i >= 0; --i) {
+ val = (val >> 8) | (((uint64_t)*ptr++) << 56);
+ }
+ val >>= (7 - zwidth) * 8;
+ } else {
+ for (int i = zwidth; i >= 0; --i) {
+ val = (val >> 8) | (((uint64_t)*ptr++) << 56);
+ }
+ }
+ return val;
+}
+
+EncodedStaticFieldValueIterator::EncodedStaticFieldValueIterator(const DexFile& dex_file,
+ DexCache* dex_cache, ClassLinker* linker, const DexFile::ClassDef& class_def) :
+ dex_file_(dex_file), dex_cache_(dex_cache), linker_(linker), array_size_(), pos_(-1), type_(0) {
+ ptr_ = dex_file.GetEncodedStaticFieldValuesArray(class_def);
+ if (ptr_ == NULL) {
+ array_size_ = 0;
+ } else {
+ array_size_ = DecodeUnsignedLeb128(&ptr_);
+ }
+ if (array_size_ > 0) {
+ Next();
+ }
+}
+
+void EncodedStaticFieldValueIterator::Next() {
+ pos_++;
+ if (pos_ >= array_size_) {
+ return;
+ }
+ byte value_type = *ptr_++;
+ byte value_arg = value_type >> kEncodedValueArgShift;
+ size_t width = value_arg + 1; // assume and correct later
+ type_ = value_type & kEncodedValueTypeMask;
+ switch (type_) {
+ case kBoolean:
+ jval_.i = (value_arg != 0) ? 1 : 0;
+ width = 0;
+ break;
+ case kByte:
+ jval_.i = ReadSignedInt(ptr_, value_arg);
+ CHECK(IsInt(8, jval_.i));
+ break;
+ case kShort:
+ jval_.i = ReadSignedInt(ptr_, value_arg);
+ CHECK(IsInt(16, jval_.i));
+ break;
+ case kChar:
+ jval_.i = ReadUnsignedInt(ptr_, value_arg, false);
+ CHECK(IsUint(16, jval_.i));
+ break;
+ case kInt:
+ jval_.i = ReadSignedInt(ptr_, value_arg);
+ break;
+ case kLong:
+ jval_.j = ReadSignedLong(ptr_, value_arg);
+ break;
+ case kFloat:
+ jval_.i = ReadUnsignedInt(ptr_, value_arg, true);
+ break;
+ case kDouble:
+ jval_.j = ReadUnsignedLong(ptr_, value_arg, true);
+ break;
+ case kString:
+ case kType:
+ case kMethod:
+ case kEnum:
+ jval_.i = ReadUnsignedInt(ptr_, value_arg, false);
+ break;
+ case kField:
+ case kArray:
+ case kAnnotation:
+ UNIMPLEMENTED(FATAL) << ": type " << type_;
+ break;
+ case kNull:
+ jval_.l = NULL;
+ width = 0;
+ break;
+ default:
+ LOG(FATAL) << "Unreached";
+ }
+ ptr_ += width;
+}
+
+void EncodedStaticFieldValueIterator::ReadValueToField(Field* field) const {
+ switch (type_) {
+ case kBoolean: field->SetBoolean(NULL, jval_.z); break;
+ case kByte: field->SetByte(NULL, jval_.b); break;
+ case kShort: field->SetShort(NULL, jval_.s); break;
+ case kChar: field->SetChar(NULL, jval_.c); break;
+ case kInt: field->SetInt(NULL, jval_.i); break;
+ case kLong: field->SetLong(NULL, jval_.j); break;
+ case kFloat: field->SetFloat(NULL, jval_.f); break;
+ case kDouble: field->SetDouble(NULL, jval_.d); break;
+ case kNull: field->SetObject(NULL, NULL); break;
+ case kString: {
+ String* resolved = linker_->ResolveString(dex_file_, jval_.i, dex_cache_);
+ field->SetObject(NULL, resolved);
+ break;
+ }
+ default: UNIMPLEMENTED(FATAL) << ": type " << type_;
+ }
+}
+
+CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item, uint32_t address) {
+ handler_.address_ = -1;
+ int32_t offset = -1;
+
+ // Short-circuit the overwhelmingly common cases.
+ switch (code_item.tries_size_) {
+ case 0:
+ break;
+ case 1: {
+ const DexFile::TryItem* tries = DexFile::GetTryItems(code_item, 0);
+ uint32_t start = tries->start_addr_;
+ if (address >= start) {
+ uint32_t end = start + tries->insn_count_;
+ if (address < end) {
+ offset = tries->handler_off_;
+ }
+ }
+ break;
+ }
+ default:
+ offset = DexFile::FindCatchHandlerOffset(code_item, code_item.tries_size_, address);
+ }
+ if (offset >= 0) {
+ const byte* handler_data = DexFile::GetCatchHandlerData(code_item, offset);
+ Init(handler_data);
+ } else {
+ // Not found, initialize as empty
+ current_data_ = NULL;
+ remaining_count_ = -1;
+ catch_all_ = false;
+ DCHECK(!HasNext());
+ }
+}
+
+void CatchHandlerIterator::Init(const byte* handler_data) {
+ current_data_ = handler_data;
+ remaining_count_ = DecodeSignedLeb128(&current_data_);
+
+ // If remaining_count_ is non-positive, then it is the negative of
+ // the number of catch types, and the catches are followed by a
+ // catch-all handler.
+ if (remaining_count_ <= 0) {
+ catch_all_ = true;
+ remaining_count_ = -remaining_count_;
+ } else {
+ catch_all_ = false;
+ }
+ Next();
+}
+
+void CatchHandlerIterator::Next() {
+ if (remaining_count_ > 0) {
+ handler_.type_idx_ = DecodeUnsignedLeb128(&current_data_);
+ handler_.address_ = DecodeUnsignedLeb128(&current_data_);
+ remaining_count_--;
+ return;
+ }
+
+ if (catch_all_) {
+ handler_.type_idx_ = DexFile::kDexNoIndex16;
+ handler_.address_ = DecodeUnsignedLeb128(&current_data_);
+ catch_all_ = false;
+ return;
+ }
+
+ // no more handler
+ remaining_count_ = -1;
+}
+
} // namespace art
diff --git a/src/dex_file.h b/src/dex_file.h
index 3acd79f916..62b99ab28b 100644
--- a/src/dex_file.h
+++ b/src/dex_file.h
@@ -10,20 +10,14 @@
#include "UniquePtr.h"
#include "globals.h"
#include "jni.h"
-#include "leb128.h"
#include "logging.h"
#include "mem_map.h"
#include "mutex.h"
#include "stringpiece.h"
-#include "strutil.h"
#include "utils.h"
namespace art {
-union JValue;
-class String;
-class Method;
-
// TODO: move all of the macro functionality into the DexCache class.
class DexFile {
public:
@@ -34,30 +28,11 @@ class DexFile {
// name of the DexFile entry within a zip archive
static const char* kClassesDex;
- static const byte kEncodedValueTypeMask = 0x1f; // 0b11111
- static const byte kEncodedValueArgShift = 5;
-
// The value of an invalid index.
static const uint32_t kDexNoIndex = 0xFFFFFFFF;
- enum ValueType {
- kByte = 0x00,
- kShort = 0x02,
- kChar = 0x03,
- kInt = 0x04,
- kLong = 0x06,
- kFloat = 0x10,
- kDouble = 0x11,
- kString = 0x17,
- kType = 0x18,
- kField = 0x19,
- kMethod = 0x1a,
- kEnum = 0x1b,
- kArray = 0x1c,
- kAnnotation = 0x1d,
- kNull = 0x1e,
- kBoolean = 0x1f
- };
+ // The value of an invalid index.
+ static const uint16_t kDexNoIndex16 = 0xFFFF;
// Raw header_item.
struct Header {
@@ -67,23 +42,23 @@ class DexFile {
uint32_t file_size_; // length of entire file
uint32_t header_size_; // offset to start of next section
uint32_t endian_tag_;
- uint32_t link_size_;
- uint32_t link_off_;
- uint32_t map_off_;
- uint32_t string_ids_size_;
- uint32_t string_ids_off_;
- uint32_t type_ids_size_;
- uint32_t type_ids_off_;
- uint32_t proto_ids_size_;
- uint32_t proto_ids_off_;
- uint32_t field_ids_size_;
- uint32_t field_ids_off_;
- uint32_t method_ids_size_;
- uint32_t method_ids_off_;
- uint32_t class_defs_size_;
- uint32_t class_defs_off_;
- uint32_t data_size_;
- uint32_t data_off_;
+ uint32_t link_size_; // unused
+ uint32_t link_off_; // unused
+ uint32_t map_off_; // unused
+ uint32_t string_ids_size_; // number of StringIds
+ uint32_t string_ids_off_; // file offset of StringIds array
+ uint32_t type_ids_size_; // number of TypeIds, we don't support more than 65535
+ uint32_t type_ids_off_; // file offset of TypeIds array
+ uint32_t proto_ids_size_; // number of ProtoIds, we don't support more than 65535
+ uint32_t proto_ids_off_; // file offset of ProtoIds array
+ uint32_t field_ids_size_; // number of FieldIds
+ uint32_t field_ids_off_; // file offset of FieldIds array
+ uint32_t method_ids_size_; // number of MethodIds
+ uint32_t method_ids_off_; // file offset of MethodIds array
+ uint32_t class_defs_size_; // number of ClassDefs
+ uint32_t class_defs_off_; // file offset of ClassDef array
+ uint32_t data_size_; // unused
+ uint32_t data_off_; // unused
private:
DISALLOW_COPY_AND_ASSIGN(Header);
};
@@ -104,26 +79,27 @@ class DexFile {
// Raw field_id_item.
struct FieldId {
- uint16_t class_idx_; // index into type_ids_ list for defining class
- uint16_t type_idx_; // index into type_ids_ for field type
- uint32_t name_idx_; // index into string_ids_ for field name
+ uint16_t class_idx_; // index into type_ids_ array for defining class
+ uint16_t type_idx_; // index into type_ids_ array for field type
+ uint32_t name_idx_; // index into string_ids_ array for field name
private:
DISALLOW_COPY_AND_ASSIGN(FieldId);
};
// Raw method_id_item.
struct MethodId {
- uint16_t class_idx_; // index into type_ids_ list for defining class
- uint16_t proto_idx_; // index into proto_ids_ for method prototype
- uint32_t name_idx_; // index into string_ids_ for method name
+ uint16_t class_idx_; // index into type_ids_ array for defining class
+ uint16_t proto_idx_; // index into proto_ids_ array for method prototype
+ uint32_t name_idx_; // index into string_ids_ array for method name
private:
DISALLOW_COPY_AND_ASSIGN(MethodId);
};
// Raw proto_id_item.
struct ProtoId {
- uint32_t shorty_idx_; // index into string_ids for shorty descriptor
- uint32_t return_type_idx_; // index into type_ids list for return type
+ uint32_t shorty_idx_; // index into string_ids array for shorty descriptor
+ uint16_t return_type_idx_; // index into type_ids array for return type
+ uint16_t pad_; // padding = 0
uint32_t parameters_off_; // file offset to type_list for parameter types
private:
DISALLOW_COPY_AND_ASSIGN(ProtoId);
@@ -131,9 +107,11 @@ class DexFile {
// Raw class_def_item.
struct ClassDef {
- uint32_t class_idx_; // index into type_ids_ for this class
+ uint16_t class_idx_; // index into type_ids_ array for this class
+ uint16_t pad1_; // padding = 0
uint32_t access_flags_;
- uint32_t superclass_idx_; // index into type_ids_ for superclass
+ uint16_t superclass_idx_; // index into type_ids_ array for superclass
+ uint16_t pad2_; // padding = 0
uint32_t interfaces_off_; // file offset to TypeList
uint32_t source_file_idx_; // index into string_ids_ for source file name
uint32_t annotations_off_; // file offset to annotations_directory_item
@@ -168,37 +146,6 @@ class DexFile {
DISALLOW_COPY_AND_ASSIGN(TypeList);
};
- class ParameterIterator { // TODO: stream
- public:
- ParameterIterator(const DexFile& dex_file, const ProtoId& proto_id)
- : dex_file_(dex_file), size_(0), pos_(0) {
- type_list_ = dex_file_.GetProtoParameters(proto_id);
- if (type_list_ != NULL) {
- size_ = type_list_->Size();
- }
- }
- bool HasNext() const { return pos_ != size_; }
- void Next() { ++pos_; }
- const char* GetDescriptor() {
- uint32_t type_idx = type_list_->GetTypeItem(pos_).type_idx_;
- return dex_file_.dexStringByTypeIdx(type_idx);
- }
- private:
- const DexFile& dex_file_;
- const TypeList* type_list_;
- uint32_t size_;
- uint32_t pos_;
- DISALLOW_IMPLICIT_CONSTRUCTORS(ParameterIterator);
- };
-
- ParameterIterator* GetParameterIterator(const ProtoId& proto_id) const {
- return new ParameterIterator(*this, proto_id);
- }
-
- const char* GetReturnTypeDescriptor(const ProtoId& proto_id) const {
- return dexStringByTypeIdx(proto_id.return_type_idx_);
- }
-
// Raw code_item.
struct CodeItem {
uint16_t registers_size_;
@@ -212,11 +159,6 @@ class DexFile {
DISALLOW_COPY_AND_ASSIGN(CodeItem);
};
- struct CatchHandlerItem {
- uint32_t type_idx_; // type index of the caught exception type
- uint32_t address_; // handler address
- };
-
// Raw try_item.
struct TryItem {
uint32_t start_addr_;
@@ -226,95 +168,6 @@ class DexFile {
DISALLOW_COPY_AND_ASSIGN(TryItem);
};
- class CatchHandlerIterator {
- public:
- CatchHandlerIterator() {
- remaining_count_ = -1;
- catch_all_ = false;
- }
-
- explicit CatchHandlerIterator(const byte* handler_data) {
- current_data_ = handler_data;
- remaining_count_ = DecodeSignedLeb128(&current_data_);
-
- // If remaining_count_ is non-positive, then it is the negative of
- // the number of catch types, and the catches are followed by a
- // catch-all handler.
- if (remaining_count_ <= 0) {
- catch_all_ = true;
- remaining_count_ = -remaining_count_;
- } else {
- catch_all_ = false;
- }
- Next();
- }
-
- const CatchHandlerItem& Get() const {
- return handler_;
- }
-
- const byte* GetData() const {
- return current_data_;
- }
-
- void Next() {
- if (remaining_count_ > 0) {
- handler_.type_idx_ = DecodeUnsignedLeb128(&current_data_);
- handler_.address_ = DecodeUnsignedLeb128(&current_data_);
- remaining_count_--;
- return;
- }
-
- if (catch_all_) {
- handler_.type_idx_ = kDexNoIndex;
- handler_.address_ = DecodeUnsignedLeb128(&current_data_);
- catch_all_ = false;
- return;
- }
-
- // no more handler
- remaining_count_ = -1;
- }
-
- bool HasNext() const {
- return remaining_count_ == -1 && catch_all_ == false;
- }
-
- private:
- CatchHandlerItem handler_;
- const byte *current_data_; // the current handler in dex file.
- int32_t remaining_count_; // number of handlers not read.
- bool catch_all_; // is there a handler that will catch all exceptions in case
- // that all typed handler does not match.
- };
-
- // Partially decoded form of class_data_item.
- struct ClassDataHeader {
- uint32_t static_fields_size_; // the number of static fields
- uint32_t instance_fields_size_; // the number of instance fields
- uint32_t direct_methods_size_; // the number of direct methods
- uint32_t virtual_methods_size_; // the number of virtual methods
- };
-
- // Decoded form of encoded_field.
- struct Field {
- uint32_t field_idx_; // index into the field_ids list for the identity of this field
- uint32_t access_flags_; // access flags for the field
- Field() {}
- private:
- DISALLOW_COPY_AND_ASSIGN(Field);
- };
-
- // Decoded form of encoded_method.
- struct Method {
- uint32_t method_idx_;
- uint32_t access_flags_;
- uint32_t code_off_;
- Method() {}
- private:
- DISALLOW_COPY_AND_ASSIGN(Method);
- };
-
typedef std::pair<const DexFile*, const DexFile::ClassDef*> ClassPathEntry;
typedef std::vector<const DexFile*> ClassPath;
@@ -347,82 +200,104 @@ class DexFile {
return *header_;
}
- // Looks up a class definition index by its class descriptor.
- bool FindClassDefIndex(const StringPiece& descriptor, uint32_t& idx) const;
-
+ // Decode the dex magic version
uint32_t GetVersion() const;
- // Looks up a class definition by its class descriptor.
- const ClassDef* FindClassDef(const StringPiece& descriptor) const;
-
// Returns the number of string identifiers in the .dex file.
size_t NumStringIds() const {
CHECK(header_ != NULL);
return header_->string_ids_size_;
}
- // Returns the number of type identifiers in the .dex file.
- size_t NumTypeIds() const {
- CHECK(header_ != NULL);
- return header_->type_ids_size_;
+ // Returns the StringId at the specified index.
+ const StringId& GetStringId(uint32_t idx) const {
+ CHECK_LT(idx, NumStringIds());
+ return string_ids_[idx];
}
- // Returns the number of prototype identifiers in the .dex file.
- size_t NumProtoIds() const {
- CHECK(header_ != NULL);
- return header_->proto_ids_size_;
+ uint32_t GetIndexForStringId(const StringId& string_id) const {
+ CHECK_GE(&string_id, string_ids_);
+ CHECK_LT(&string_id, string_ids_ + header_->string_ids_size_);
+ return &string_id - string_ids_;
}
- // Returns the number of field identifiers in the .dex file.
- size_t NumFieldIds() const {
- CHECK(header_ != NULL);
- return header_->field_ids_size_;
+ int32_t GetStringLength(const StringId& string_id) const;
+
+ // Returns a pointer to the UTF-8 string data referred to by the given string_id.
+ const char* GetStringDataAndLength(const StringId& string_id, int32_t* length) const;
+
+ const char* GetStringData(const StringId& string_id) const {
+ int32_t length;
+ return GetStringDataAndLength(string_id, &length);
}
- // Returns the number of method identifiers in the .dex file.
- size_t NumMethodIds() const {
- CHECK(header_ != NULL);
- return header_->method_ids_size_;
+ // return the UTF-8 encoded string with the specified string_id index
+ const char* StringDataAndLengthByIdx(uint32_t idx, int32_t* unicode_length) const {
+ if (idx == kDexNoIndex) {
+ *unicode_length = 0;
+ return NULL;
+ }
+ const StringId& string_id = GetStringId(idx);
+ return GetStringDataAndLength(string_id, unicode_length);
}
- // Returns the number of class definitions in the .dex file.
- size_t NumClassDefs() const {
+ const char* StringDataByIdx(uint32_t idx) const {
+ int32_t unicode_length;
+ return StringDataAndLengthByIdx(idx, &unicode_length);
+ }
+
+ // Looks up a string id for a given string
+ const StringId* FindStringId(const std::string& string) const;
+
+ // Returns the number of type identifiers in the .dex file.
+ size_t NumTypeIds() const {
CHECK(header_ != NULL);
- return header_->class_defs_size_;
+ return header_->type_ids_size_;
}
- // Returns a pointer to the memory mapped class data.
- // TODO: return a stream
- const byte* GetClassData(const ClassDef& class_def) const {
- if (class_def.class_data_off_ == 0) {
- return NULL;
- } else {
- return base_ + class_def.class_data_off_;
- }
+ // Returns the TypeId at the specified index.
+ const TypeId& GetTypeId(uint32_t idx) const {
+ CHECK_LT(idx, NumTypeIds());
+ return type_ids_[idx];
}
- // Decodes the header section from the class data bytes.
- ClassDataHeader ReadClassDataHeader(const byte** class_data) const {
- CHECK(class_data != NULL);
- ClassDataHeader header;
- memset(&header, 0, sizeof(ClassDataHeader));
- if (*class_data != NULL) {
- header.static_fields_size_ = DecodeUnsignedLeb128(class_data);
- header.instance_fields_size_ = DecodeUnsignedLeb128(class_data);
- header.direct_methods_size_ = DecodeUnsignedLeb128(class_data);
- header.virtual_methods_size_ = DecodeUnsignedLeb128(class_data);
- }
- return header;
+ uint16_t GetIndexForTypeId(const TypeId& type_id) const {
+ CHECK_GE(&type_id, type_ids_);
+ CHECK_LT(&type_id, type_ids_ + header_->type_ids_size_);
+ size_t result = &type_id - type_ids_;
+ DCHECK(result < 65536);
+ return static_cast<uint16_t>(result);
}
- // Returns the class descriptor string of a class definition.
- const char* GetClassDescriptor(const ClassDef& class_def) const {
- return dexStringByTypeIdx(class_def.class_idx_);
+ // Get the descriptor string associated with a given type index.
+ const char* StringByTypeIdx(uint32_t idx, int32_t* unicode_length) const {
+ const TypeId& type_id = GetTypeId(idx);
+ return StringDataAndLengthByIdx(type_id.descriptor_idx_, unicode_length);
+ }
+
+ const char* StringByTypeIdx(uint32_t idx) const {
+ const TypeId& type_id = GetTypeId(idx);
+ return StringDataByIdx(type_id.descriptor_idx_);
}
// Returns the type descriptor string of a type id.
const char* GetTypeDescriptor(const TypeId& type_id) const {
- return dexStringById(type_id.descriptor_idx_);
+ return StringDataByIdx(type_id.descriptor_idx_);
+ }
+
+ // Looks up a type for the given string index
+ const TypeId* FindTypeId(uint32_t string_idx) const;
+
+ // Returns the number of field identifiers in the .dex file.
+ size_t NumFieldIds() const {
+ CHECK(header_ != NULL);
+ return header_->field_ids_size_;
+ }
+
+ // Returns the FieldId at the specified index.
+ const FieldId& GetFieldId(uint32_t idx) const {
+ CHECK_LT(idx, NumFieldIds());
+ return field_ids_[idx];
}
// Returns the declaring class descriptor string of a field id.
@@ -439,9 +314,31 @@ class DexFile {
// Returns the name of a field id.
const char* GetFieldName(const FieldId& field_id) const {
- return dexStringById(field_id.name_idx_);
+ return StringDataByIdx(field_id.name_idx_);
+ }
+
+ // Returns the number of method identifiers in the .dex file.
+ size_t NumMethodIds() const {
+ CHECK(header_ != NULL);
+ return header_->method_ids_size_;
+ }
+
+ // Returns the MethodId at the specified index.
+ const MethodId& GetMethodId(uint32_t idx) const {
+ CHECK_LT(idx, NumMethodIds());
+ return method_ids_[idx];
}
+ uint32_t GetIndexForMethodId(const MethodId& method_id) const {
+ CHECK_GE(&method_id, method_ids_);
+ CHECK_LT(&method_id, method_ids_ + header_->method_ids_size_);
+ return &method_id - method_ids_;
+ }
+
+ // Looks up a method by its class_dex, name and proto_id
+ const MethodId* FindMethodId(const DexFile::TypeId& klass, const DexFile::StringId& name,
+ const DexFile::ProtoId& signature) const;
+
// Returns the declaring class descriptor string of a method id.
const char* GetMethodDeclaringClassDescriptor(const MethodId& method_id) const {
const DexFile::TypeId& type_id = GetTypeId(method_id.class_idx_);
@@ -455,49 +352,47 @@ class DexFile {
// Returns the signature of a method id.
const std::string GetMethodSignature(const MethodId& method_id) const {
- return CreateMethodDescriptor(method_id.proto_idx_, NULL);
+ return CreateMethodSignature(method_id.proto_idx_, NULL);
}
// Returns the name of a method id.
const char* GetMethodName(const MethodId& method_id) const {
- return dexStringById(method_id.name_idx_);
+ return StringDataByIdx(method_id.name_idx_);
}
- // Returns the StringId at the specified index.
- const StringId& GetStringId(uint32_t idx) const {
- CHECK_LT(idx, NumStringIds());
- return string_ids_[idx];
+ // Returns the shorty of a method id.
+ const char* GetMethodShorty(const MethodId& method_id) const {
+ return StringDataByIdx(GetProtoId(method_id.proto_idx_).shorty_idx_);
}
- // Returns the TypeId at the specified index.
- const TypeId& GetTypeId(uint32_t idx) const {
- CHECK_LT(idx, NumTypeIds());
- return type_ids_[idx];
+ // Returns the number of class definitions in the .dex file.
+ size_t NumClassDefs() const {
+ CHECK(header_ != NULL);
+ return header_->class_defs_size_;
}
- // Returns the FieldId at the specified index.
- const FieldId& GetFieldId(uint32_t idx) const {
- CHECK_LT(idx, NumFieldIds());
- return field_ids_[idx];
+ // Returns the ClassDef at the specified index.
+ const ClassDef& GetClassDef(uint32_t idx) const {
+ CHECK_LT(idx, NumClassDefs());
+ return class_defs_[idx];
}
- // Returns the MethodId at the specified index.
- const MethodId& GetMethodId(uint32_t idx) const {
- CHECK_LT(idx, NumMethodIds());
- return method_ids_[idx];
+ uint32_t GetIndexForClassDef(const ClassDef& class_def) const {
+ CHECK_GE(&class_def, class_defs_);
+ CHECK_LT(&class_def, class_defs_ + header_->class_defs_size_);
+ return &class_def - class_defs_;
}
- // Returns the ProtoId at the specified index.
- const ProtoId& GetProtoId(uint32_t idx) const {
- CHECK_LT(idx, NumProtoIds());
- return proto_ids_[idx];
+ // Returns the class descriptor string of a class definition.
+ const char* GetClassDescriptor(const ClassDef& class_def) const {
+ return StringByTypeIdx(class_def.class_idx_);
}
- // Returns the ClassDef at the specified index.
- const ClassDef& GetClassDef(uint32_t idx) const {
- CHECK_LT(idx, NumClassDefs());
- return class_defs_[idx];
- }
+ // Looks up a class definition by its class descriptor.
+ const ClassDef* FindClassDef(const StringPiece& descriptor) const;
+
+ // Looks up a class definition index by its class descriptor.
+ bool FindClassDefIndex(const StringPiece& descriptor, uint32_t& idx) const;
const TypeList* GetInterfacesList(const ClassDef& class_def) const {
if (class_def.interfaces_off_ == 0) {
@@ -508,10 +403,16 @@ class DexFile {
}
}
- const CodeItem* GetCodeItem(const Method& method) const {
- return GetCodeItem(method.code_off_);
+ // Returns a pointer to the raw memory mapped class_data_item
+ const byte* GetClassData(const ClassDef& class_def) const {
+ if (class_def.class_data_off_ == 0) {
+ return NULL;
+ } else {
+ return base_ + class_def.class_data_off_;
+ }
}
+ //
const CodeItem* GetCodeItem(const uint32_t code_off_) const {
if (code_off_ == 0) {
return NULL; // native or abstract method
@@ -521,10 +422,43 @@ class DexFile {
}
}
+ const char* GetReturnTypeDescriptor(const ProtoId& proto_id) const {
+ return StringByTypeIdx(proto_id.return_type_idx_);
+ }
+
+ // Returns the number of prototype identifiers in the .dex file.
+ size_t NumProtoIds() const {
+ CHECK(header_ != NULL);
+ return header_->proto_ids_size_;
+ }
+
+ // Returns the ProtoId at the specified index.
+ const ProtoId& GetProtoId(uint32_t idx) const {
+ CHECK_LT(idx, NumProtoIds());
+ return proto_ids_[idx];
+ }
+
+ uint16_t GetIndexForProtoId(const ProtoId& proto_id) const {
+ CHECK_GE(&proto_id, proto_ids_);
+ CHECK_LT(&proto_id, proto_ids_ + header_->proto_ids_size_);
+ return &proto_id - proto_ids_;
+ }
+
+ // Looks up a proto id for a given return type and signature type list
+ const ProtoId* FindProtoId(uint16_t return_type_id,
+ const std::vector<uint16_t>& signature_type_ids_) const;
+
+ // Given a signature place the type ids into the given vector, returns true on success
+ bool CreateTypeList(uint16_t* return_type_idx, std::vector<uint16_t>* param_type_idxs,
+ const std::string& signature) const;
+
+ // Given a proto_idx decode the type list and return type into a method signature
+ std::string CreateMethodSignature(uint32_t proto_idx, int32_t* unicode_length) const;
+
// Returns the short form method descriptor for the given prototype.
const char* GetShorty(uint32_t proto_idx) const {
const ProtoId& proto_id = GetProtoId(proto_idx);
- return dexStringById(proto_id.shorty_idx_);
+ return StringDataByIdx(proto_id.shorty_idx_);
}
const TypeList* GetProtoParameters(const ProtoId& proto_id) const {
@@ -536,9 +470,7 @@ class DexFile {
}
}
- std::string CreateMethodDescriptor(uint32_t proto_idx, int32_t* unicode_length) const;
-
- const byte* GetEncodedArray(const ClassDef& class_def) const {
+ const byte* GetEncodedStaticFieldValuesArray(const ClassDef& class_def) const {
if (class_def.static_values_off_ == 0) {
return 0;
} else {
@@ -546,158 +478,27 @@ class DexFile {
}
}
- int32_t GetStringLength(const StringId& string_id) const {
- const byte* ptr = base_ + string_id.string_data_off_;
- return DecodeUnsignedLeb128(&ptr);
- }
-
- ValueType ReadEncodedValue(const byte** encoded_value, JValue* value) const;
-
- // From libdex...
-
- // Returns a pointer to the UTF-8 string data referred to by the
- // given string_id.
- const char* GetStringData(const StringId& string_id, int32_t* length) const {
- CHECK(length != NULL);
- const byte* ptr = base_ + string_id.string_data_off_;
- *length = DecodeUnsignedLeb128(&ptr);
- return reinterpret_cast<const char*>(ptr);
- }
-
- const char* GetStringData(const StringId& string_id) const {
- int32_t length;
- return GetStringData(string_id, &length);
- }
-
- // return the UTF-8 encoded string with the specified string_id index
- const char* dexStringById(uint32_t idx, int32_t* unicode_length) const {
- if (idx == kDexNoIndex) {
- *unicode_length = 0;
- return NULL;
- }
- const StringId& string_id = GetStringId(idx);
- return GetStringData(string_id, unicode_length);
- }
-
- const char* dexStringById(uint32_t idx) const {
- int32_t unicode_length;
- return dexStringById(idx, &unicode_length);
- }
-
- // Get the descriptor string associated with a given type index.
- const char* dexStringByTypeIdx(uint32_t idx, int32_t* unicode_length) const {
- const TypeId& type_id = GetTypeId(idx);
- return dexStringById(type_id.descriptor_idx_, unicode_length);
- }
-
- const char* dexStringByTypeIdx(uint32_t idx) const {
- const TypeId& type_id = GetTypeId(idx);
- return dexStringById(type_id.descriptor_idx_);
- }
-
- // TODO: encoded_field is actually a stream of bytes
- void dexReadClassDataField(const byte** encoded_field,
- DexFile::Field* field,
- uint32_t* last_idx) const {
- uint32_t idx = *last_idx + DecodeUnsignedLeb128(encoded_field);
- field->access_flags_ = DecodeUnsignedLeb128(encoded_field);
- field->field_idx_ = idx;
- *last_idx = idx;
- }
-
- // TODO: encoded_method is actually a stream of bytes
- void dexReadClassDataMethod(const byte** encoded_method,
- DexFile::Method* method,
- uint32_t* last_idx) const {
- uint32_t idx = *last_idx + DecodeUnsignedLeb128(encoded_method);
- method->access_flags_ = DecodeUnsignedLeb128(encoded_method);
- method->code_off_ = DecodeUnsignedLeb128(encoded_method);
- method->method_idx_ = idx;
- *last_idx = idx;
- }
-
- static const TryItem* dexGetTryItems(const CodeItem& code_item, uint32_t offset) {
+ static const TryItem* GetTryItems(const CodeItem& code_item, uint32_t offset) {
const uint16_t* insns_end_ = &code_item.insns_[code_item.insns_size_in_code_units_];
return reinterpret_cast<const TryItem*>
(RoundUp(reinterpret_cast<uint32_t>(insns_end_), 4)) + offset;
}
// Get the base of the encoded data for the given DexCode.
- static const byte* dexGetCatchHandlerData(const CodeItem& code_item, uint32_t offset) {
- const byte* handler_data = reinterpret_cast<const byte*>
- (dexGetTryItems(code_item, code_item.tries_size_));
+ static const byte* GetCatchHandlerData(const CodeItem& code_item, uint32_t offset) {
+ const byte* handler_data =
+ reinterpret_cast<const byte*>(GetTryItems(code_item, code_item.tries_size_));
return handler_data + offset;
}
// Find the handler associated with a given address, if any.
// Initializes the given iterator and returns true if a match is
// found. Returns end if there is no applicable handler.
- static CatchHandlerIterator dexFindCatchHandler(const CodeItem& code_item, uint32_t address) {
- CatchHandlerItem handler;
- handler.address_ = -1;
- int32_t offset = -1;
-
- // Short-circuit the overwhelmingly common cases.
- switch (code_item.tries_size_) {
- case 0:
- break;
- case 1: {
- const TryItem* tries = dexGetTryItems(code_item, 0);
- uint32_t start = tries->start_addr_;
- if (address < start)
- break;
-
- uint32_t end = start + tries->insn_count_;
- if (address >= end)
- break;
-
- offset = tries->handler_off_;
- break;
- }
- default:
- offset = dexFindCatchHandlerOffset0(code_item, code_item.tries_size_, address);
- }
-
- if (offset >= 0) {
- const byte* handler_data = dexGetCatchHandlerData(code_item, offset);
- return CatchHandlerIterator(handler_data);
- }
- return CatchHandlerIterator();
- }
-
- static int32_t dexFindCatchHandlerOffset0(const CodeItem &code_item,
- int32_t tries_size,
- uint32_t address) {
- // Note: Signed type is important for max and min.
- int32_t min = 0;
- int32_t max = tries_size - 1;
-
- while (max >= min) {
- int32_t guess = (min + max) >> 1;
- const TryItem* pTry = dexGetTryItems(code_item, guess);
- uint32_t start = pTry->start_addr_;
-
- if (address < start) {
- max = guess - 1;
- continue;
- }
-
- uint32_t end = start + pTry->insn_count_;
- if (address >= end) {
- min = guess + 1;
- continue;
- }
-
- // We have a winner!
- return (int32_t) pTry->handler_off_;
- }
-
- // No match.
- return -1;
- }
+ static int32_t FindCatchHandlerOffset(const CodeItem &code_item, int32_t tries_size,
+ uint32_t address);
// Get the pointer to the start of the debugging data
- const byte* dexGetDebugInfoStream(const CodeItem* code_item) const {
+ const byte* GetDebugInfoStream(const CodeItem* code_item) const {
if (code_item->debug_info_off_ == 0) {
return NULL;
} else {
@@ -718,22 +519,7 @@ class DexFile {
const char* descriptor,
const char* signature);
- static bool LineNumForPcCb(void* cnxt, uint32_t address, uint32_t line_num) {
- LineNumFromPcContext* context = (LineNumFromPcContext*) cnxt;
-
- // We know that this callback will be called in
- // ascending address order, so keep going until we find
- // a match or we've just gone past it.
- if (address > context->address_) {
- // The line number from the previous positions callback
- // wil be the final result.
- return true;
- } else {
- context->line_num_ = line_num;
- return address == context->address_;
- }
- }
-
+ static bool LineNumForPcCb(void* cnxt, uint32_t address, uint32_t line_num);
// Debug info opcodes and constants
enum {
@@ -753,22 +539,14 @@ class DexFile {
};
struct LocalInfo {
- LocalInfo() : name_(NULL), start_address_(0), is_live_(false) {}
-
- // E.g., list
- const char* name_;
-
- // E.g., Ljava/util/LinkedList;
- const char* descriptor_;
+ LocalInfo() : name_(NULL), descriptor_(NULL), signature_(NULL), start_address_(0),
+ is_live_(false) {}
- // E.g., java.util.LinkedList<java.lang.Integer>
- const char* signature_;
-
- // PC location where the local is first defined.
- uint16_t start_address_;
-
- // Is the local defined and live.
- bool is_live_;
+ const char* name_; // E.g., list
+ const char* descriptor_; // E.g., Ljava/util/LinkedList;
+ const char* signature_; // E.g., java.util.LinkedList<java.lang.Integer>
+ uint16_t start_address_; // PC location where the local is first defined.
+ bool is_live_; // Is the local defined and live.
private:
DISALLOW_COPY_AND_ASSIGN(LocalInfo);
@@ -800,38 +578,21 @@ class DexFile {
// Returns -2 for native methods (as expected in exception traces).
//
// This is used by runtime; therefore use art::Method not art::DexFile::Method.
- int32_t GetLineNumFromPC(const art::Method* method, uint32_t rel_pc) const;
+ int32_t GetLineNumFromPC(const Method* method, uint32_t rel_pc) const;
- void dexDecodeDebugInfo0(const CodeItem* code_item, const art::Method* method,
- DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
- void* cnxt, const byte* stream, LocalInfo* local_in_reg) const;
+ void DecodeDebugInfo0(const CodeItem* code_item, const Method* method,
+ DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
+ void* cnxt, const byte* stream, LocalInfo* local_in_reg) const;
- void dexDecodeDebugInfo(const CodeItem* code_item, const art::Method* method,
- DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
- void* cnxt) const {
- const byte* stream = dexGetDebugInfoStream(code_item);
- LocalInfo local_in_reg[code_item->registers_size_];
+ void DecodeDebugInfo(const CodeItem* code_item, const Method* method,
+ DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
+ void* cnxt) const;
- if (stream != NULL) {
- dexDecodeDebugInfo0(code_item, method, posCb, local_cb, cnxt, stream, local_in_reg);
- }
- for (int reg = 0; reg < code_item->registers_size_; reg++) {
- InvokeLocalCbIfLive(cnxt, reg, code_item->insns_size_in_code_units_, local_in_reg, local_cb);
- }
- }
-
- // TODO: const reference
- uint32_t dexGetIndexForClassDef(const ClassDef* class_def) const {
- CHECK_GE(class_def, class_defs_);
- CHECK_LT(class_def, class_defs_ + header_->class_defs_size_);
- return class_def - class_defs_;
- }
-
- const char* dexGetSourceFile(const ClassDef& class_def) const {
+ const char* GetSourceFile(const ClassDef& class_def) const {
if (class_def.source_file_idx_ == 0xffffffff) {
return NULL;
} else {
- return dexStringById(class_def.source_file_idx_);
+ return StringDataByIdx(class_def.source_file_idx_);
}
}
@@ -889,6 +650,8 @@ class DexFile {
bool IsMagicValid();
// The index of descriptors to class definition indexes.
+ // TODO: given type_ids are sorted by string_id index, and string_ids are alphabetically, class
+ // lookup can be done with a binary search. Is the index necessary?
typedef std::map<const StringPiece, uint32_t> Index;
Index index_;
@@ -933,6 +696,261 @@ class DexFile {
const ClassDef* class_defs_;
};
+// Iterate over a dex file's ProtoId's paramters
+class DexFileParameterIterator {
+ public:
+ DexFileParameterIterator(const DexFile& dex_file, const DexFile::ProtoId& proto_id)
+ : dex_file_(dex_file), size_(0), pos_(0) {
+ type_list_ = dex_file_.GetProtoParameters(proto_id);
+ if (type_list_ != NULL) {
+ size_ = type_list_->Size();
+ }
+ }
+ bool HasNext() const { return pos_ < size_; }
+ void Next() { ++pos_; }
+ uint16_t GetTypeId() {
+ return type_list_->GetTypeItem(pos_).type_idx_;
+ }
+ const char* GetDescriptor() {
+ return dex_file_.StringByTypeIdx(GetTypeId());
+ }
+ private:
+ const DexFile& dex_file_;
+ const DexFile::TypeList* type_list_;
+ uint32_t size_;
+ uint32_t pos_;
+ DISALLOW_IMPLICIT_CONSTRUCTORS(DexFileParameterIterator);
+};
+
+// Iterate and decode class_data_item
+class ClassDataItemIterator {
+ public:
+ ClassDataItemIterator(const DexFile& dex_file, const byte* raw_class_data_item)
+ : dex_file_(dex_file), pos_(0), ptr_pos_(raw_class_data_item), last_idx_(0) {
+ ReadClassDataHeader();
+ if (EndOfInstanceFieldsPos() > 0) {
+ ReadClassDataField();
+ } else if (EndOfVirtualMethodsPos() > 0) {
+ ReadClassDataMethod();
+ }
+ }
+ uint32_t NumStaticFields() const {
+ return header_.static_fields_size_;
+ }
+ uint32_t NumInstanceFields() const {
+ return header_.instance_fields_size_;
+ }
+ uint32_t NumDirectMethods() const {
+ return header_.direct_methods_size_;
+ }
+ uint32_t NumVirtualMethods() const {
+ return header_.virtual_methods_size_;
+ }
+ bool HasNextStaticField() const {
+ return pos_ < EndOfStaticFieldsPos();
+ }
+ bool HasNextInstanceField() const {
+ return pos_ >= EndOfStaticFieldsPos() && pos_ < EndOfInstanceFieldsPos();
+ }
+ bool HasNextDirectMethod() const {
+ return pos_ >= EndOfInstanceFieldsPos() && pos_ < EndOfDirectMethodsPos();
+ }
+ bool HasNextVirtualMethod() const {
+ return pos_ >= EndOfDirectMethodsPos() && pos_ < EndOfVirtualMethodsPos();
+ }
+ bool HasNext() const {
+ return pos_ < EndOfVirtualMethodsPos();
+ }
+ void Next() {
+ pos_++;
+ if (pos_ < EndOfStaticFieldsPos()) {
+ last_idx_ = GetMemberIndex();
+ ReadClassDataField();
+ } else if (pos_ == EndOfStaticFieldsPos() && NumInstanceFields() > 0) {
+ last_idx_ = 0; // transition to next array, reset last index
+ ReadClassDataField();
+ } else if (pos_ < EndOfInstanceFieldsPos()) {
+ last_idx_ = GetMemberIndex();
+ ReadClassDataField();
+ } else if (pos_ == EndOfInstanceFieldsPos() && NumDirectMethods() > 0) {
+ last_idx_ = 0; // transition to next array, reset last index
+ ReadClassDataMethod();
+ } else if (pos_ < EndOfDirectMethodsPos()) {
+ last_idx_ = GetMemberIndex();
+ ReadClassDataMethod();
+ } else if (pos_ == EndOfDirectMethodsPos() && NumVirtualMethods() > 0) {
+ last_idx_ = 0; // transition to next array, reset last index
+ ReadClassDataMethod();
+ } else if (pos_ < EndOfVirtualMethodsPos()) {
+ last_idx_ = GetMemberIndex();
+ ReadClassDataMethod();
+ } else {
+ DCHECK(!HasNext());
+ }
+ }
+ uint32_t GetMemberIndex() const {
+ if (pos_ < EndOfInstanceFieldsPos()) {
+ return last_idx_ + field_.field_idx_delta_;
+ } else {
+ CHECK_LT(pos_, EndOfVirtualMethodsPos());
+ return last_idx_ + method_.method_idx_delta_;
+ }
+ }
+ uint32_t GetMemberAccessFlags() const {
+ if (pos_ < EndOfInstanceFieldsPos()) {
+ return field_.access_flags_;
+ } else {
+ CHECK_LT(pos_, EndOfVirtualMethodsPos());
+ return method_.access_flags_;
+ }
+ }
+ const DexFile::CodeItem* GetMethodCodeItem() const {
+ return dex_file_.GetCodeItem(method_.code_off_);
+ }
+ uint32_t GetMethodCodeItemOffset() const {
+ return method_.code_off_;
+ }
+ private:
+ // A dex file's class_data_item is leb128 encoded, this structure holds a decoded form of the
+ // header for a class_data_item
+ struct ClassDataHeader {
+ uint32_t static_fields_size_; // the number of static fields
+ uint32_t instance_fields_size_; // the number of instance fields
+ uint32_t direct_methods_size_; // the number of direct methods
+ uint32_t virtual_methods_size_; // the number of virtual methods
+ } header_;
+
+ // Read and decode header from a class_data_item stream into header
+ void ReadClassDataHeader();
+
+ uint32_t EndOfStaticFieldsPos() const {
+ return header_.static_fields_size_;
+ }
+ uint32_t EndOfInstanceFieldsPos() const {
+ return EndOfStaticFieldsPos() + header_.instance_fields_size_;
+ }
+ uint32_t EndOfDirectMethodsPos() const {
+ return EndOfInstanceFieldsPos() + header_.direct_methods_size_;
+ }
+ uint32_t EndOfVirtualMethodsPos() const {
+ return EndOfDirectMethodsPos() + header_.virtual_methods_size_;
+ }
+
+ // A decoded version of the field of a class_data_item
+ struct ClassDataField {
+ uint32_t field_idx_delta_; // delta of index into the field_ids array for FieldId
+ uint32_t access_flags_; // access flags for the field
+ ClassDataField() : field_idx_delta_(0), access_flags_(0) {}
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ClassDataField);
+ } field_;
+
+ // Read and decode a field from a class_data_item stream into field
+ void ReadClassDataField();
+
+ // A decoded version of the method of a class_data_item
+ struct ClassDataMethod {
+ uint32_t method_idx_delta_; // delta of index into the method_ids array for MethodId
+ uint32_t access_flags_;
+ uint32_t code_off_;
+ ClassDataMethod() : method_idx_delta_(0), access_flags_(0), code_off_(0) {}
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ClassDataMethod);
+ } method_;
+
+ // Read and decode a method from a class_data_item stream into method
+ void ReadClassDataMethod();
+
+ const DexFile& dex_file_;
+ size_t pos_; // integral number of items passed
+ const byte* ptr_pos_; // pointer into stream of class_data_item
+ uint32_t last_idx_; // last read field or method index to apply delta to
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ClassDataItemIterator);
+};
+
+class ClassLinker;
+class DexCache;
+class Field;
+
+class EncodedStaticFieldValueIterator {
+ public:
+ EncodedStaticFieldValueIterator(const DexFile& dex_file, DexCache* dex_cache,
+ ClassLinker* linker, const DexFile::ClassDef& class_def);
+
+ void ReadValueToField(Field* field) const;
+
+ bool HasNext() { return pos_ < array_size_; }
+
+ void Next();
+ private:
+ enum ValueType {
+ kByte = 0x00,
+ kShort = 0x02,
+ kChar = 0x03,
+ kInt = 0x04,
+ kLong = 0x06,
+ kFloat = 0x10,
+ kDouble = 0x11,
+ kString = 0x17,
+ kType = 0x18,
+ kField = 0x19,
+ kMethod = 0x1a,
+ kEnum = 0x1b,
+ kArray = 0x1c,
+ kAnnotation = 0x1d,
+ kNull = 0x1e,
+ kBoolean = 0x1f
+ };
+
+ static const byte kEncodedValueTypeMask = 0x1f; // 0b11111
+ static const byte kEncodedValueArgShift = 5;
+
+ const DexFile& dex_file_;
+ DexCache* dex_cache_; // dex cache to resolve literal objects
+ ClassLinker* linker_; // linker to resolve literal objects
+ size_t array_size_; // size of array
+ size_t pos_; // current position
+ const byte* ptr_; // pointer into encoded data array
+ byte type_; // type of current encoded value
+ jvalue jval_; // value of current encoded value
+ DISALLOW_IMPLICIT_CONSTRUCTORS(EncodedStaticFieldValueIterator);
+};
+
+class CatchHandlerIterator {
+ public:
+ CatchHandlerIterator(const DexFile::CodeItem& code_item, uint32_t address);
+ explicit CatchHandlerIterator(const byte* handler_data) {
+ Init(handler_data);
+ }
+
+ uint16_t GetHandlerTypeIndex() const {
+ return handler_.type_idx_;
+ }
+ uint32_t GetHandlerAddress() const {
+ return handler_.address_;
+ }
+ void Next();
+ bool HasNext() const {
+ return remaining_count_ != -1 || catch_all_;
+ }
+ // End of this set of catch blocks, convenience method to locate next set of catch blocks
+ const byte* EndDataPointer() const {
+ CHECK(!HasNext());
+ return current_data_;
+ }
+ private:
+ void Init(const byte* handler_data);
+
+ struct CatchHandlerItem {
+ uint16_t type_idx_; // type index of the caught exception type
+ uint32_t address_; // handler address
+ } handler_;
+ const byte *current_data_; // the current handler in dex file.
+ int32_t remaining_count_; // number of handlers not read.
+ bool catch_all_; // is there a handler that will catch all exceptions in case
+ // that all typed handler does not match.
+};
+
} // namespace art
#endif // ART_SRC_DEX_FILE_H_
diff --git a/src/dex_file_test.cc b/src/dex_file_test.cc
index e33276b881..6f99551e1a 100644
--- a/src/dex_file_test.cc
+++ b/src/dex_file_test.cc
@@ -81,65 +81,118 @@ TEST_F(DexFileTest, ClassDefs) {
EXPECT_STREQ("LNested;", raw->GetClassDescriptor(c1));
}
-TEST_F(DexFileTest, CreateMethodDescriptor) {
- UniquePtr<const DexFile> raw(OpenTestDexFile("CreateMethodDescriptor"));
+TEST_F(DexFileTest, CreateMethodSignature) {
+ UniquePtr<const DexFile> raw(OpenTestDexFile("CreateMethodSignature"));
ASSERT_TRUE(raw.get() != NULL);
EXPECT_EQ(1U, raw->NumClassDefs());
const DexFile::ClassDef& class_def = raw->GetClassDef(0);
- ASSERT_STREQ("LCreateMethodDescriptor;", raw->GetClassDescriptor(class_def));
+ ASSERT_STREQ("LCreateMethodSignature;", raw->GetClassDescriptor(class_def));
const byte* class_data = raw->GetClassData(class_def);
ASSERT_TRUE(class_data != NULL);
- DexFile::ClassDataHeader header = raw->ReadClassDataHeader(&class_data);
+ ClassDataItemIterator it(*raw.get(), class_data);
- EXPECT_EQ(1u, header.direct_methods_size_);
+ EXPECT_EQ(1u, it.NumDirectMethods());
- // Check the descriptor for the static initializer.
+ // Check the signature for the static initializer.
{
- uint32_t last_idx = 0;
- ASSERT_EQ(1U, header.direct_methods_size_);
- DexFile::Method method;
- raw->dexReadClassDataMethod(&class_data, &method, &last_idx);
- const DexFile::MethodId& method_id = raw->GetMethodId(method.method_idx_);
+ ASSERT_EQ(1U, it.NumDirectMethods());
+ const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex());
uint32_t proto_idx = method_id.proto_idx_;
- const char* name = raw->dexStringById(method_id.name_idx_);
+ const char* name = raw->StringDataByIdx(method_id.name_idx_);
ASSERT_STREQ("<init>", name);
int32_t length;
- std::string descriptor(raw->CreateMethodDescriptor(proto_idx, &length));
- ASSERT_EQ("()V", descriptor);
+ std::string signature(raw->CreateMethodSignature(proto_idx, &length));
+ ASSERT_EQ("()V", signature);
}
// Check both virtual methods.
- ASSERT_EQ(2U, header.virtual_methods_size_);
- uint32_t last_idx = 0;
-
+ ASSERT_EQ(2U, it.NumVirtualMethods());
{
- DexFile::Method method;
- raw->dexReadClassDataMethod(&class_data, &method, &last_idx);
- const DexFile::MethodId& method_id = raw->GetMethodId(method.method_idx_);
+ it.Next();
+ const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex());
- const char* name = raw->dexStringById(method_id.name_idx_);
+ const char* name = raw->StringDataByIdx(method_id.name_idx_);
ASSERT_STREQ("m1", name);
uint32_t proto_idx = method_id.proto_idx_;
int32_t length;
- std::string descriptor(raw->CreateMethodDescriptor(proto_idx, &length));
- ASSERT_EQ("(IDJLjava/lang/Object;)Ljava/lang/Float;", descriptor);
+ std::string signature(raw->CreateMethodSignature(proto_idx, &length));
+ ASSERT_EQ("(IDJLjava/lang/Object;)Ljava/lang/Float;", signature);
}
{
- DexFile::Method method;
- raw->dexReadClassDataMethod(&class_data, &method, &last_idx);
- const DexFile::MethodId& method_id = raw->GetMethodId(method.method_idx_);
+ it.Next();
+ const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex());
- const char* name = raw->dexStringById(method_id.name_idx_);
+ const char* name = raw->StringDataByIdx(method_id.name_idx_);
ASSERT_STREQ("m2", name);
uint32_t proto_idx = method_id.proto_idx_;
int32_t length;
- std::string descriptor(raw->CreateMethodDescriptor(proto_idx, &length));
- ASSERT_EQ("(ZSC)LCreateMethodDescriptor;", descriptor);
+ std::string signature(raw->CreateMethodSignature(proto_idx, &length));
+ ASSERT_EQ("(ZSC)LCreateMethodSignature;", signature);
+ }
+}
+
+TEST_F(DexFileTest, FindStringId) {
+ UniquePtr<const DexFile> raw(OpenTestDexFile("CreateMethodSignature"));
+ ASSERT_TRUE(raw.get() != NULL);
+ EXPECT_EQ(1U, raw->NumClassDefs());
+
+ const char* strings[] = { "LCreateMethodSignature;", "Ljava/lang/Float;", "Ljava/lang/Object;",
+ "D", "I", "J", NULL };
+ for (size_t i = 0; strings[i] != NULL; i++) {
+ const char* str = strings[i];
+ const DexFile::StringId* str_id = raw->FindStringId(str);
+ const char* dex_str = raw->GetStringData(*str_id);
+ EXPECT_STREQ(dex_str, str);
+ }
+}
+
+TEST_F(DexFileTest, FindTypeId) {
+ for (size_t i = 0; i < java_lang_dex_file_->NumTypeIds(); i++) {
+ const char* type_str = java_lang_dex_file_->StringByTypeIdx(i);
+ const DexFile::StringId* type_str_id = java_lang_dex_file_->FindStringId(type_str);
+ ASSERT_TRUE(type_str_id != NULL);
+ uint32_t type_str_idx = java_lang_dex_file_->GetIndexForStringId(*type_str_id);
+ const DexFile::TypeId* type_id = java_lang_dex_file_->FindTypeId(type_str_idx);
+ ASSERT_TRUE(type_id != NULL);
+ EXPECT_EQ(java_lang_dex_file_->GetIndexForTypeId(*type_id), i);
+ }
+}
+
+TEST_F(DexFileTest, FindProtoId) {
+ for (size_t i = 0; i < java_lang_dex_file_->NumProtoIds(); i++) {
+ const DexFile::ProtoId& to_find = java_lang_dex_file_->GetProtoId(i);
+ const DexFile::TypeList* to_find_tl = java_lang_dex_file_->GetProtoParameters(to_find);
+ std::vector<uint16_t> to_find_types;
+ if (to_find_tl != NULL) {
+ for (size_t j = 0; j < to_find_tl->Size(); j++) {
+ to_find_types.push_back(to_find_tl->GetTypeItem(j).type_idx_);
+ }
+ }
+ const DexFile::ProtoId* found =
+ java_lang_dex_file_->FindProtoId(to_find.return_type_idx_, to_find_types);
+ ASSERT_TRUE(found != NULL);
+ EXPECT_EQ(java_lang_dex_file_->GetIndexForProtoId(*found), i);
+ }
+}
+
+TEST_F(DexFileTest, FindMethodId) {
+ for (size_t i = 0; i < java_lang_dex_file_->NumMethodIds(); i++) {
+ const DexFile::MethodId& to_find = java_lang_dex_file_->GetMethodId(i);
+ const DexFile::TypeId& klass = java_lang_dex_file_->GetTypeId(to_find.class_idx_);
+ const DexFile::StringId& name = java_lang_dex_file_->GetStringId(to_find.name_idx_);
+ const DexFile::ProtoId& signature = java_lang_dex_file_->GetProtoId(to_find.proto_idx_);
+ const DexFile::MethodId* found = java_lang_dex_file_->FindMethodId(klass, name, signature);
+ int32_t length;
+ ASSERT_TRUE(found != NULL) << "Didn't find method " << i << ": "
+ << java_lang_dex_file_->StringByTypeIdx(to_find.class_idx_) << "."
+ << java_lang_dex_file_->GetStringData(name)
+ << java_lang_dex_file_->CreateMethodSignature(to_find.proto_idx_, &length);
+ EXPECT_EQ(java_lang_dex_file_->GetIndexForMethodId(*found), i);
}
}
diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc
index 3ad9996995..d162aec730 100644
--- a/src/dex_verifier.cc
+++ b/src/dex_verifier.cc
@@ -11,6 +11,7 @@
#include "dex_instruction_visitor.h"
#include "dex_verifier.h"
#include "intern_table.h"
+#include "leb128.h"
#include "logging.h"
#include "runtime.h"
#include "stringpiece.h"
@@ -1031,7 +1032,7 @@ bool DexVerifier::ScanTryCatchBlocks() {
return true;
}
uint32_t insns_size = code_item_->insns_size_in_code_units_;
- const DexFile::TryItem* tries = DexFile::dexGetTryItems(*code_item_, 0);
+ const DexFile::TryItem* tries = DexFile::GetTryItems(*code_item_, 0);
for (uint32_t idx = 0; idx < tries_size; idx++) {
const DexFile::TryItem* try_item = &tries[idx];
@@ -1052,14 +1053,13 @@ bool DexVerifier::ScanTryCatchBlocks() {
}
}
/* Iterate over each of the handlers to verify target addresses. */
- const byte* handlers_ptr = DexFile::dexGetCatchHandlerData(*code_item_, 0);
+ const byte* handlers_ptr = DexFile::GetCatchHandlerData(*code_item_, 0);
uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
ClassLinker* linker = Runtime::Current()->GetClassLinker();
for (uint32_t idx = 0; idx < handlers_size; idx++) {
- DexFile::CatchHandlerIterator iterator(handlers_ptr);
- for (; !iterator.HasNext(); iterator.Next()) {
- const DexFile::CatchHandlerItem& handler = iterator.Get();
- uint32_t dex_pc= handler.address_;
+ CatchHandlerIterator iterator(handlers_ptr);
+ for (; iterator.HasNext(); iterator.Next()) {
+ uint32_t dex_pc= iterator.GetHandlerAddress();
if (!insn_flags_[dex_pc].IsOpcode()) {
Fail(VERIFY_ERROR_GENERIC) << "exception handler starts at bad address (" << dex_pc << ")";
return false;
@@ -1067,15 +1067,15 @@ bool DexVerifier::ScanTryCatchBlocks() {
insn_flags_[dex_pc].SetBranchTarget();
// Ensure exception types are resolved so that they don't need resolution to be delivered,
// unresolved exception types will be ignored by exception delivery
- if (handler.type_idx_ != DexFile::kDexNoIndex) {
- Class* exception_type = linker->ResolveType(handler.type_idx_, method_);
+ if (iterator.GetHandlerTypeIndex() != DexFile::kDexNoIndex16) {
+ Class* exception_type = linker->ResolveType(iterator.GetHandlerTypeIndex(), method_);
if (exception_type == NULL) {
DCHECK(Thread::Current()->IsExceptionPending());
Thread::Current()->ClearException();
}
}
}
- handlers_ptr = iterator.GetData();
+ handlers_ptr = iterator.EndDataPointer();
}
return true;
}
@@ -1221,7 +1221,7 @@ bool DexVerifier::CheckNewInstance(uint32_t idx) {
return false;
}
// We don't need the actual class, just a pointer to the class name.
- const char* descriptor = dex_file_->dexStringByTypeIdx(idx);
+ const char* descriptor = dex_file_->StringByTypeIdx(idx);
if (descriptor[0] != 'L') {
Fail(VERIFY_ERROR_GENERIC) << "can't call new-instance on type '" << descriptor << "'";
return false;
@@ -1254,7 +1254,7 @@ bool DexVerifier::CheckNewArray(uint32_t idx) {
return false;
}
int bracket_count = 0;
- const char* descriptor = dex_file_->dexStringByTypeIdx(idx);
+ const char* descriptor = dex_file_->StringByTypeIdx(idx);
const char* cp = descriptor;
while (*cp++ == '[') {
bracket_count++;
@@ -1575,7 +1575,7 @@ bool DexVerifier::SetTypesFromSignature() {
}
const DexFile::ProtoId& proto_id = dex_file_->GetProtoId(method_->GetProtoIdx());
- DexFile::ParameterIterator iterator(*dex_file_, proto_id);
+ DexFileParameterIterator iterator(*dex_file_, proto_id);
for (; iterator.HasNext(); iterator.Next()) {
const char* descriptor = iterator.GetDescriptor();
@@ -2364,7 +2364,7 @@ bool DexVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
uint32_t method_idx = dec_insn.vB_;
const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
- descriptor = dex_file_->dexStringByTypeIdx(return_type_idx);
+ descriptor = dex_file_->StringByTypeIdx(return_type_idx);
} else {
descriptor = called_method->GetReturnTypeDescriptor();
}
@@ -2442,7 +2442,7 @@ bool DexVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
uint32_t method_idx = dec_insn.vB_;
const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
- descriptor = dex_file_->dexStringByTypeIdx(return_type_idx);
+ descriptor = dex_file_->StringByTypeIdx(return_type_idx);
} else {
descriptor = called_method->GetReturnTypeDescriptor();
}
@@ -2463,7 +2463,7 @@ bool DexVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
uint32_t method_idx = dec_insn.vB_;
const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
- descriptor = dex_file_->dexStringByTypeIdx(return_type_idx);
+ descriptor = dex_file_->StringByTypeIdx(return_type_idx);
} else {
descriptor = called_method->GetReturnTypeDescriptor();
}
@@ -2518,7 +2518,7 @@ bool DexVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
uint32_t method_idx = dec_insn.vB_;
const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
- descriptor = dex_file_->dexStringByTypeIdx(return_type_idx);
+ descriptor = dex_file_->StringByTypeIdx(return_type_idx);
} else {
descriptor = abs_method->GetReturnTypeDescriptor();
}
@@ -2891,11 +2891,10 @@ bool DexVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
*/
if ((opcode_flag & Instruction::kThrow) != 0 && insn_flags_[work_insn_idx_].IsInTry()) {
bool within_catch_all = false;
- DexFile::CatchHandlerIterator iterator =
- DexFile::dexFindCatchHandler(*code_item_, work_insn_idx_);
+ CatchHandlerIterator iterator(*code_item_, work_insn_idx_);
- for (; !iterator.HasNext(); iterator.Next()) {
- if (iterator.Get().type_idx_ == DexFile::kDexNoIndex) {
+ for (; iterator.HasNext(); iterator.Next()) {
+ if (iterator.GetHandlerTypeIndex() == DexFile::kDexNoIndex16) {
within_catch_all = true;
}
/*
@@ -2903,7 +2902,7 @@ bool DexVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
* "work_regs", because at runtime the exception will be thrown before the instruction
* modifies any registers.
*/
- if (!UpdateRegisters(iterator.Get().address_, saved_line_.get())) {
+ if (!UpdateRegisters(iterator.GetHandlerAddress(), saved_line_.get())) {
return false;
}
}
@@ -2953,7 +2952,7 @@ bool DexVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
}
const RegType& DexVerifier::ResolveClassAndCheckAccess(uint32_t class_idx) {
- const char* descriptor = dex_file_->dexStringByTypeIdx(class_idx);
+ const char* descriptor = dex_file_->StringByTypeIdx(class_idx);
Class* referrer = method_->GetDeclaringClass();
Class* klass = method_->GetDexCacheResolvedTypes()->Get(class_idx);
const RegType& result =
@@ -2977,17 +2976,16 @@ const RegType& DexVerifier::ResolveClassAndCheckAccess(uint32_t class_idx) {
const RegType& DexVerifier::GetCaughtExceptionType() {
const RegType* common_super = NULL;
if (code_item_->tries_size_ != 0) {
- const byte* handlers_ptr = DexFile::dexGetCatchHandlerData(*code_item_, 0);
+ const byte* handlers_ptr = DexFile::GetCatchHandlerData(*code_item_, 0);
uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
for (uint32_t i = 0; i < handlers_size; i++) {
- DexFile::CatchHandlerIterator iterator(handlers_ptr);
- for (; !iterator.HasNext(); iterator.Next()) {
- DexFile::CatchHandlerItem handler = iterator.Get();
- if (handler.address_ == (uint32_t) work_insn_idx_) {
- if (handler.type_idx_ == DexFile::kDexNoIndex) {
+ CatchHandlerIterator iterator(handlers_ptr);
+ for (; iterator.HasNext(); iterator.Next()) {
+ if (iterator.GetHandlerAddress() == (uint32_t) work_insn_idx_) {
+ if (iterator.GetHandlerTypeIndex() == DexFile::kDexNoIndex16) {
common_super = &reg_types_.JavaLangThrowable();
} else {
- const RegType& exception = ResolveClassAndCheckAccess(handler.type_idx_);
+ const RegType& exception = ResolveClassAndCheckAccess(iterator.GetHandlerTypeIndex());
/* TODO: on error do we want to keep going? If we don't fail this we run the risk of
* having a non-Throwable introduced at runtime. However, that won't pass an instanceof
* test, so is essentially harmless.
@@ -3006,7 +3004,7 @@ const RegType& DexVerifier::GetCaughtExceptionType() {
}
}
}
- handlers_ptr = iterator.GetData();
+ handlers_ptr = iterator.EndDataPointer();
}
}
if (common_super == NULL) {
@@ -3028,7 +3026,7 @@ Method* DexVerifier::ResolveMethodAndCheckAccess(uint32_t method_idx, bool is_di
}
Class* klass = klass_type.GetClass();
const char* name = dex_file_->GetMethodName(method_id);
- std::string signature(dex_file_->CreateMethodDescriptor(method_id.proto_idx_, NULL));
+ std::string signature(dex_file_->CreateMethodSignature(method_id.proto_idx_, NULL));
if (is_direct) {
res_method = klass->FindDirectMethod(name, signature);
} else if (klass->IsInterface()) {
diff --git a/src/exception_test.cc b/src/exception_test.cc
index df6432923a..559636f417 100644
--- a/src/exception_test.cc
+++ b/src/exception_test.cc
@@ -67,28 +67,30 @@ TEST_F(ExceptionTest, FindCatchHandler) {
ASSERT_NE(0u, code_item->insns_size_in_code_units_);
const struct DexFile::TryItem *t0, *t1;
- t0 = dex_->dexGetTryItems(*code_item, 0);
- t1 = dex_->dexGetTryItems(*code_item, 1);
+ t0 = dex_->GetTryItems(*code_item, 0);
+ t1 = dex_->GetTryItems(*code_item, 1);
EXPECT_LE(t0->start_addr_, t1->start_addr_);
-
- DexFile::CatchHandlerIterator iter =
- dex_->dexFindCatchHandler(*code_item, 4 /* Dex PC in the first try block */);
- ASSERT_EQ(false, iter.HasNext());
- EXPECT_STREQ("Ljava/io/IOException;", dex_->dexStringByTypeIdx(iter.Get().type_idx_));
- iter.Next();
- ASSERT_EQ(false, iter.HasNext());
- EXPECT_STREQ("Ljava/lang/Exception;", dex_->dexStringByTypeIdx(iter.Get().type_idx_));
- iter.Next();
- ASSERT_EQ(true, iter.HasNext());
-
- iter = dex_->dexFindCatchHandler(*code_item, 8 /* Dex PC in the second try block */);
- ASSERT_EQ(false, iter.HasNext());
- EXPECT_STREQ("Ljava/io/IOException;", dex_->dexStringByTypeIdx(iter.Get().type_idx_));
- iter.Next();
- ASSERT_EQ(true, iter.HasNext());
-
- iter = dex_->dexFindCatchHandler(*code_item, 11 /* Dex PC not in any try block */);
- ASSERT_EQ(true, iter.HasNext());
+ {
+ CatchHandlerIterator iter(*code_item, 4 /* Dex PC in the first try block */);
+ EXPECT_STREQ("Ljava/io/IOException;", dex_->StringByTypeIdx(iter.GetHandlerTypeIndex()));
+ ASSERT_TRUE(iter.HasNext());
+ iter.Next();
+ EXPECT_STREQ("Ljava/lang/Exception;", dex_->StringByTypeIdx(iter.GetHandlerTypeIndex()));
+ ASSERT_TRUE(iter.HasNext());
+ iter.Next();
+ EXPECT_FALSE(iter.HasNext());
+ }
+ {
+ CatchHandlerIterator iter(*code_item, 8 /* Dex PC in the second try block */);
+ EXPECT_STREQ("Ljava/io/IOException;", dex_->StringByTypeIdx(iter.GetHandlerTypeIndex()));
+ ASSERT_TRUE(iter.HasNext());
+ iter.Next();
+ EXPECT_FALSE(iter.HasNext());
+ }
+ {
+ CatchHandlerIterator iter(*code_item, 11 /* Dex PC not in any try block */);
+ EXPECT_FALSE(iter.HasNext());
+ }
}
TEST_F(ExceptionTest, StackTraceElement) {
diff --git a/src/image_test.cc b/src/image_test.cc
index 3e64d95666..88ddae9da0 100644
--- a/src/image_test.cc
+++ b/src/image_test.cc
@@ -21,6 +21,14 @@ TEST_F(ImageTest, WriteRead) {
bool success_oat = OatWriter::Create(tmp_oat.GetFile(), NULL, *compiler_.get());
ASSERT_TRUE(success_oat);
+ // Force all system classes into memory
+ for (size_t i = 0; i < java_lang_dex_file_->NumClassDefs(); i++) {
+ const DexFile::ClassDef& class_def = java_lang_dex_file_->GetClassDef(i);
+ const char* descriptor = java_lang_dex_file_->GetClassDescriptor(class_def);
+ Class* klass = class_linker_->FindSystemClass(descriptor);
+ EXPECT_TRUE(klass != NULL) << descriptor;
+ }
+
ImageWriter writer;
ScratchFile tmp_image;
const uintptr_t requested_image_base = 0x60000000;
diff --git a/src/jni_compiler.cc b/src/jni_compiler.cc
index 127b53d548..5a4056aee9 100644
--- a/src/jni_compiler.cc
+++ b/src/jni_compiler.cc
@@ -7,6 +7,7 @@
#include "assembler.h"
#include "calling_convention.h"
+#include "class_linker.h"
#include "compiled_method.h"
#include "constants.h"
#include "jni_internal.h"
@@ -55,7 +56,12 @@ JniCompiler::~JniCompiler() {}
// registers, a reference to the method object is supplied as part of this
// convention.
//
-CompiledMethod* JniCompiler::Compile(const Method* native_method) {
+CompiledMethod* JniCompiler::Compile(bool is_direct, uint32_t method_idx,
+ const ClassLoader* class_loader, const DexFile& dex_file) {
+ ClassLinker* linker = Runtime::Current()->GetClassLinker();
+ DexCache* dex_cache = linker->FindDexCache(dex_file);
+ Method* native_method = linker->ResolveMethod(dex_file, method_idx, dex_cache,
+ class_loader, is_direct);
CHECK(native_method->IsNative());
// Calling conventions used to iterate over parameters to method
@@ -435,7 +441,6 @@ CompiledMethod* JniCompiler::Compile(const Method* native_method) {
return new CompiledMethod(instruction_set_,
managed_code,
frame_size,
- jni_conv->ReturnPcOffset(),
jni_conv->CoreSpillMask(),
jni_conv->FpSpillMask());
#undef __
diff --git a/src/jni_compiler.h b/src/jni_compiler.h
index a6d56026ab..dbdfa68e3a 100644
--- a/src/jni_compiler.h
+++ b/src/jni_compiler.h
@@ -25,7 +25,8 @@ class JniCompiler {
explicit JniCompiler(InstructionSet instruction_set);
~JniCompiler();
- CompiledMethod* Compile(const Method* method);
+ CompiledMethod* Compile(bool is_direct, uint32_t method_idx, const ClassLoader* class_loader,
+ const DexFile& dex_file);
// Stub to perform native method symbol lookup via dlsym
// TODO: remove from JniCompiler
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 5787c652b1..9936f259f1 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -101,6 +101,42 @@ T AddLocalReference(JNIEnv* public_env, const Object* const_obj) {
return reinterpret_cast<T>(ref);
}
+size_t NumArgArrayBytes(const char* shorty) {
+ size_t num_bytes = 0;
+ size_t end = strlen(shorty);
+ for (size_t i = 1; i < end; ++i) {
+ char ch = shorty[i];
+ if (ch == 'D' || ch == 'J') {
+ num_bytes += 8;
+ } else if (ch == 'L') {
+ // Argument is a reference or an array. The shorty descriptor
+ // does not distinguish between these types.
+ num_bytes += sizeof(Object*);
+ } else {
+ num_bytes += 4;
+ }
+ }
+ return num_bytes;
+}
+
+static size_t NumArgArrayBytes(const String* shorty) {
+ size_t num_bytes = 0;
+ size_t end = shorty->GetLength();
+ for (size_t i = 1; i < end; ++i) {
+ char ch = shorty->CharAt(i);
+ if (ch == 'D' || ch == 'J') {
+ num_bytes += 8;
+ } else if (ch == 'L') {
+ // Argument is a reference or an array. The shorty descriptor
+ // does not distinguish between these types.
+ num_bytes += sizeof(Object*);
+ } else {
+ num_bytes += 4;
+ }
+ }
+ return num_bytes;
+}
+
// For external use.
template<typename T>
T Decode(JNIEnv* public_env, jobject obj) {
@@ -139,11 +175,11 @@ T Decode(ScopedJniThreadState& ts, jobject obj) {
return reinterpret_cast<T>(ts.Self()->DecodeJObject(obj));
}
-byte* CreateArgArray(JNIEnv* public_env, Method* method, va_list ap) {
+static byte* CreateArgArray(JNIEnv* public_env, Method* method, va_list ap) {
JNIEnvExt* env = reinterpret_cast<JNIEnvExt*>(public_env);
- size_t num_bytes = method->NumArgArrayBytes();
- UniquePtr<byte[]> arg_array(new byte[num_bytes]);
const String* shorty = method->GetShorty();
+ size_t num_bytes = NumArgArrayBytes(shorty);
+ UniquePtr<byte[]> arg_array(new byte[num_bytes]);
for (int i = 1, offset = 0; i < shorty->GetLength(); ++i) {
switch (shorty->CharAt(i)) {
case 'Z':
@@ -177,9 +213,9 @@ byte* CreateArgArray(JNIEnv* public_env, Method* method, va_list ap) {
return arg_array.release();
}
-byte* CreateArgArray(JNIEnv* public_env, Method* method, jvalue* args) {
+static byte* CreateArgArray(JNIEnv* public_env, Method* method, jvalue* args) {
JNIEnvExt* env = reinterpret_cast<JNIEnvExt*>(public_env);
- size_t num_bytes = method->NumArgArrayBytes();
+ size_t num_bytes = NumArgArrayBytes(method->GetShorty());
UniquePtr<byte[]> arg_array(new byte[num_bytes]);
const String* shorty = method->GetShorty();
for (int i = 1, offset = 0; i < shorty->GetLength(); ++i) {
@@ -215,14 +251,14 @@ byte* CreateArgArray(JNIEnv* public_env, Method* method, jvalue* args) {
return arg_array.release();
}
-JValue InvokeWithArgArray(JNIEnv* public_env, Object* receiver, Method* method, byte* args) {
+static JValue InvokeWithArgArray(JNIEnv* public_env, Object* receiver, Method* method, byte* args) {
JNIEnvExt* env = reinterpret_cast<JNIEnvExt*>(public_env);
JValue result;
method->Invoke(env->self, receiver, args, &result);
return result;
}
-JValue InvokeWithVarArgs(JNIEnv* public_env, jobject obj, jmethodID mid, va_list args) {
+static JValue InvokeWithVarArgs(JNIEnv* public_env, jobject obj, jmethodID mid, va_list args) {
JNIEnvExt* env = reinterpret_cast<JNIEnvExt*>(public_env);
Object* receiver = Decode<Object*>(env, obj);
Method* method = DecodeMethod(mid);
@@ -230,11 +266,12 @@ JValue InvokeWithVarArgs(JNIEnv* public_env, jobject obj, jmethodID mid, va_list
return InvokeWithArgArray(env, receiver, method, arg_array.get());
}
-Method* FindVirtualMethod(Object* receiver, Method* method) {
+static Method* FindVirtualMethod(Object* receiver, Method* method) {
return receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(method);
}
-JValue InvokeVirtualOrInterfaceWithJValues(JNIEnv* public_env, jobject obj, jmethodID mid, jvalue* args) {
+static JValue InvokeVirtualOrInterfaceWithJValues(JNIEnv* public_env, jobject obj, jmethodID mid,
+ jvalue* args) {
JNIEnvExt* env = reinterpret_cast<JNIEnvExt*>(public_env);
Object* receiver = Decode<Object*>(env, obj);
Method* method = FindVirtualMethod(receiver, DecodeMethod(mid));
@@ -242,7 +279,8 @@ JValue InvokeVirtualOrInterfaceWithJValues(JNIEnv* public_env, jobject obj, jmet
return InvokeWithArgArray(env, receiver, method, arg_array.get());
}
-JValue InvokeVirtualOrInterfaceWithVarArgs(JNIEnv* public_env, jobject obj, jmethodID mid, va_list args) {
+static JValue InvokeVirtualOrInterfaceWithVarArgs(JNIEnv* public_env, jobject obj, jmethodID mid,
+ va_list args) {
JNIEnvExt* env = reinterpret_cast<JNIEnvExt*>(public_env);
Object* receiver = Decode<Object*>(env, obj);
Method* method = FindVirtualMethod(receiver, DecodeMethod(mid));
@@ -255,7 +293,7 @@ JValue InvokeVirtualOrInterfaceWithVarArgs(JNIEnv* public_env, jobject obj, jmet
// (i.e. "a/b/C" rather than "La/b/C;"). Arrays of reference types are an
// exception; there the "L;" must be present ("[La/b/C;"). Historically we've
// supported names with dots too (such as "a.b.C").
-std::string NormalizeJniClassDescriptor(const char* name) {
+static std::string NormalizeJniClassDescriptor(const char* name) {
std::string result;
// Add the missing "L;" if necessary.
if (name[0] == '[') {
@@ -274,13 +312,13 @@ std::string NormalizeJniClassDescriptor(const char* name) {
return result;
}
-void ThrowNoSuchMethodError(ScopedJniThreadState& ts, Class* c, const char* name, const char* sig, const char* kind) {
+static void ThrowNoSuchMethodError(ScopedJniThreadState& ts, Class* c, const char* name, const char* sig, const char* kind) {
std::string class_descriptor(c->GetDescriptor()->ToModifiedUtf8());
ts.Self()->ThrowNewExceptionF("Ljava/lang/NoSuchMethodError;",
"no %s method \"%s.%s%s\"", kind, class_descriptor.c_str(), name, sig);
}
-jmethodID FindMethodID(ScopedJniThreadState& ts, jclass jni_class, const char* name, const char* sig, bool is_static) {
+static jmethodID FindMethodID(ScopedJniThreadState& ts, jclass jni_class, const char* name, const char* sig, bool is_static) {
Class* c = Decode<Class*>(ts, jni_class);
if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true)) {
return NULL;
@@ -308,7 +346,7 @@ jmethodID FindMethodID(ScopedJniThreadState& ts, jclass jni_class, const char* n
return EncodeMethod(method);
}
-const ClassLoader* GetClassLoader(Thread* self) {
+static const ClassLoader* GetClassLoader(Thread* self) {
Frame frame = self->GetTopOfStack();
Method* method = frame.GetMethod();
if (method == NULL || PrettyMethod(method, false) == "java.lang.Runtime.nativeLoad") {
@@ -317,7 +355,7 @@ const ClassLoader* GetClassLoader(Thread* self) {
return method->GetDeclaringClass()->GetClassLoader();
}
-jfieldID FindFieldID(ScopedJniThreadState& ts, jclass jni_class, const char* name, const char* sig, bool is_static) {
+static jfieldID FindFieldID(ScopedJniThreadState& ts, jclass jni_class, const char* name, const char* sig, bool is_static) {
Class* c = Decode<Class*>(ts, jni_class);
if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true)) {
return NULL;
@@ -359,13 +397,13 @@ jfieldID FindFieldID(ScopedJniThreadState& ts, jclass jni_class, const char* nam
return EncodeField(field);
}
-void PinPrimitiveArray(ScopedJniThreadState& ts, const Array* array) {
+static void PinPrimitiveArray(ScopedJniThreadState& ts, const Array* array) {
JavaVMExt* vm = ts.Vm();
MutexLock mu(vm->pins_lock);
vm->pin_table.Add(array);
}
-void UnpinPrimitiveArray(ScopedJniThreadState& ts, const Array* array) {
+static void UnpinPrimitiveArray(ScopedJniThreadState& ts, const Array* array) {
JavaVMExt* vm = ts.Vm();
MutexLock mu(vm->pins_lock);
vm->pin_table.Remove(array);
@@ -396,13 +434,14 @@ void ReleasePrimitiveArray(ScopedJniThreadState& ts, ArrayT java_array, jint mod
}
}
-void ThrowAIOOBE(ScopedJniThreadState& ts, Array* array, jsize start, jsize length, const char* identifier) {
+static void ThrowAIOOBE(ScopedJniThreadState& ts, Array* array, jsize start, jsize length, const char* identifier) {
std::string type(PrettyTypeOf(array));
ts.Self()->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
"%s offset=%d length=%d %s.length=%d",
type.c_str(), start, length, identifier, array->GetLength());
}
-void ThrowSIOOBE(ScopedJniThreadState& ts, jsize start, jsize length, jsize array_length) {
+
+static void ThrowSIOOBE(ScopedJniThreadState& ts, jsize start, jsize length, jsize array_length) {
ts.Self()->ThrowNewExceptionF("Ljava/lang/StringIndexOutOfBoundsException;",
"offset=%d length=%d string.length()=%d", start, length, array_length);
}
@@ -429,18 +468,18 @@ void SetPrimitiveArrayRegion(ScopedJniThreadState& ts, JavaArrayT java_array, js
}
}
-jclass InitDirectByteBufferClass(JNIEnv* env) {
+static jclass InitDirectByteBufferClass(JNIEnv* env) {
ScopedLocalRef<jclass> buffer_class(env, env->FindClass("java/nio/ReadWriteDirectByteBuffer"));
CHECK(buffer_class.get() != NULL);
return reinterpret_cast<jclass>(env->NewGlobalRef(buffer_class.get()));
}
-jclass GetDirectByteBufferClass(JNIEnv* env) {
+static jclass GetDirectByteBufferClass(JNIEnv* env) {
static jclass buffer_class = InitDirectByteBufferClass(env);
return buffer_class;
}
-jint JII_AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args, bool as_daemon) {
+static jint JII_AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args, bool as_daemon) {
if (vm == NULL || p_env == NULL) {
return JNI_ERR;
}
diff --git a/src/jni_internal.h b/src/jni_internal.h
index 25e9e62ce7..6950dae847 100644
--- a/src/jni_internal.h
+++ b/src/jni_internal.h
@@ -60,6 +60,7 @@ inline jmethodID EncodeMethod(Method* method) {
return reinterpret_cast<jmethodID>(method);
}
+size_t NumArgArrayBytes(const char* shorty);
JValue InvokeWithJValues(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args);
struct JavaVMExt : public JavaVM {
diff --git a/src/jni_internal_arm.cc b/src/jni_internal_arm.cc
index f1ed092d1b..dadf7b4220 100644
--- a/src/jni_internal_arm.cc
+++ b/src/jni_internal_arm.cc
@@ -29,14 +29,15 @@ namespace arm {
// register and transfer arguments from the array into register and on
// the stack, if needed. On return, the thread register must be
// shuffled and the return value must be store into the result JValue.
-CompiledInvokeStub* ArmCreateInvokeStub(const Method* method) {
+CompiledInvokeStub* ArmCreateInvokeStub(bool is_static, const char* shorty) {
UniquePtr<ArmAssembler> assembler(
down_cast<ArmAssembler*>(Assembler::Create(kArm)));
#define __ assembler->
+ size_t num_arg_array_bytes = NumArgArrayBytes(shorty);
// Size of frame - spill of R4,R9/LR + Method* + possible receiver + arg array
size_t unpadded_frame_size = (4 * kPointerSize) +
- (method->IsStatic() ? 0 : kPointerSize) +
- method->NumArgArrayBytes();
+ (is_static ? 0 : kPointerSize) +
+ num_arg_array_bytes;
size_t frame_size = RoundUp(unpadded_frame_size, kStackAlignment);
// Spill R4,R9 and LR
@@ -53,14 +54,14 @@ CompiledInvokeStub* ArmCreateInvokeStub(const Method* method) {
__ AddConstant(SP, -frame_size + (3 * kPointerSize));
// Can either get 3 or 2 arguments into registers
- size_t reg_bytes = (method->IsStatic() ? 3 : 2) * kPointerSize;
+ size_t reg_bytes = (is_static ? 3 : 2) * kPointerSize;
// Bytes passed by stack
size_t stack_bytes;
- if (method->NumArgArrayBytes() > reg_bytes) {
- stack_bytes = method->NumArgArrayBytes() - reg_bytes;
+ if (num_arg_array_bytes > reg_bytes) {
+ stack_bytes = num_arg_array_bytes - reg_bytes;
} else {
stack_bytes = 0;
- reg_bytes = method->NumArgArrayBytes();
+ reg_bytes = num_arg_array_bytes;
}
// Method* at bottom of frame is null thereby terminating managed stack crawls
@@ -75,12 +76,12 @@ CompiledInvokeStub* ArmCreateInvokeStub(const Method* method) {
// we're displaced off of the arguments by the spill space for the incoming
// arguments, the Method* and possibly the receiver
- int sp_offset = reg_bytes + (method->IsStatic() ? 1 : 2) * kPointerSize + off;
+ int sp_offset = reg_bytes + (is_static ? 1 : 2) * kPointerSize + off;
__ StoreToOffset(kStoreWord, IP, SP, sp_offset);
}
// Move all the register arguments into place.
- if (method->IsStatic()) {
+ if (is_static) {
if (reg_bytes > 0) {
__ LoadFromOffset(kLoadWord, R1, R3, 0);
if (reg_bytes > 4) {
@@ -100,16 +101,17 @@ CompiledInvokeStub* ArmCreateInvokeStub(const Method* method) {
}
// Load the code pointer we are about to call.
- __ LoadFromOffset(kLoadWord, IP, R0, method->GetCodeOffset().Int32Value());
+ __ LoadFromOffset(kLoadWord, IP, R0, Method::GetCodeOffset().Int32Value());
// Do the call.
__ blx(IP);
// If the method returns a value, store it to the result pointer.
- if (!method->IsReturnVoid()) {
+ if (shorty[0] != 'V') {
// Load the result JValue pointer of the stub caller's out args.
__ LoadFromOffset(kLoadWord, IP, SP, frame_size);
- __ StoreToOffset(method->IsReturnALongOrDouble() ? kStoreWordPair : kStoreWord, R0, IP, 0);
+ StoreOperandType type = (shorty[0] == 'J' || shorty[0] == 'D') ? kStoreWordPair : kStoreWord;
+ __ StoreToOffset(type, R0, IP, 0);
}
// Remove the frame less the spilled R4, R9 and LR
diff --git a/src/jni_internal_x86.cc b/src/jni_internal_x86.cc
index 891971d22f..7d931bab8c 100644
--- a/src/jni_internal_x86.cc
+++ b/src/jni_internal_x86.cc
@@ -25,14 +25,15 @@ namespace x86 {
// "running" state the remaining responsibilities of this routine are
// to save the native registers and set up the managed registers. On
// return, the return value must be store into the result JValue.
-CompiledInvokeStub* X86CreateInvokeStub(const Method* method) {
+CompiledInvokeStub* X86CreateInvokeStub(bool is_static, const char* shorty) {
UniquePtr<X86Assembler> assembler(
down_cast<X86Assembler*>(Assembler::Create(kX86)));
#define __ assembler->
+ size_t num_arg_array_bytes = NumArgArrayBytes(shorty);
// Size of frame - return address + Method* + possible receiver + arg array
size_t frame_size = (2 * kPointerSize) +
- (method->IsStatic() ? 0 : kPointerSize) +
- method->NumArgArrayBytes();
+ (is_static ? 0 : kPointerSize) +
+ num_arg_array_bytes;
size_t pad_size = RoundUp(frame_size, kStackAlignment) - frame_size;
__ movl(EAX, Address(ESP, 4)); // EAX = method
@@ -45,20 +46,20 @@ CompiledInvokeStub* X86CreateInvokeStub(const Method* method) {
}
// Push/copy arguments
- for (size_t off = method->NumArgArrayBytes(); off > 0; off -= kPointerSize) {
+ for (size_t off = num_arg_array_bytes; off > 0; off -= kPointerSize) {
__ pushl(Address(EDX, off - kPointerSize));
}
- if (!method->IsStatic()) {
+ if (!is_static) {
__ pushl(ECX);
}
// Push 0 as NULL Method* thereby terminating managed stack crawls
__ pushl(Immediate(0));
- __ call(Address(EAX, method->GetCodeOffset())); // Call code off of method
+ __ call(Address(EAX, Method::GetCodeOffset())); // Call code off of method
// pop arguments up to the return address
__ addl(ESP, Immediate(frame_size + pad_size - kPointerSize));
- char ch = method->GetShorty()->CharAt(0);
+ char ch = shorty[0];
if (ch != 'V') {
// Load the result JValue pointer.
__ movl(ECX, Address(ESP, 20));
diff --git a/src/monitor.cc b/src/monitor.cc
index b9a94590f3..3f041e4e83 100644
--- a/src/monitor.cc
+++ b/src/monitor.cc
@@ -831,7 +831,7 @@ void Monitor::TranslateLocation(const Method* method, uint32_t pc,
const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
const DexFile::ClassDef* class_def = dex_file.FindClassDef(c->GetDescriptor()->ToModifiedUtf8());
- source_file = dex_file.dexGetSourceFile(*class_def);
+ source_file = dex_file.GetSourceFile(*class_def);
line_number = dex_file.GetLineNumFromPC(method, method->ToDexPC(pc));
}
diff --git a/src/oat.cc b/src/oat.cc
index 1a615fe83e..0089410ee4 100644
--- a/src/oat.cc
+++ b/src/oat.cc
@@ -68,7 +68,6 @@ void OatHeader::SetExecutableOffset(uint32_t executable_offset) {
OatMethodOffsets::OatMethodOffsets()
: code_offset_(0),
frame_size_in_bytes_(0),
- return_pc_offset_in_bytes_(0),
core_spill_mask_(0),
fp_spill_mask_(0),
mapping_table_offset_(0),
@@ -77,7 +76,6 @@ OatMethodOffsets::OatMethodOffsets()
OatMethodOffsets::OatMethodOffsets(uint32_t code_offset,
uint32_t frame_size_in_bytes,
- uint32_t return_pc_offset_in_bytes,
uint32_t core_spill_mask,
uint32_t fp_spill_mask,
uint32_t mapping_table_offset,
@@ -85,7 +83,6 @@ OatMethodOffsets::OatMethodOffsets(uint32_t code_offset,
uint32_t invoke_stub_offset)
: code_offset_(code_offset),
frame_size_in_bytes_(frame_size_in_bytes),
- return_pc_offset_in_bytes_(return_pc_offset_in_bytes),
core_spill_mask_(core_spill_mask),
fp_spill_mask_(fp_spill_mask),
mapping_table_offset_(mapping_table_offset),
diff --git a/src/oat.h b/src/oat.h
index ff50599a36..0ffc80fdcb 100644
--- a/src/oat.h
+++ b/src/oat.h
@@ -41,7 +41,6 @@ class PACKED OatMethodOffsets {
OatMethodOffsets();
OatMethodOffsets(uint32_t code_offset,
uint32_t frame_size_in_bytes,
- uint32_t return_pc_offset_in_bytes,
uint32_t core_spill_mask,
uint32_t fp_spill_mask,
uint32_t mapping_table_offset,
@@ -51,7 +50,6 @@ class PACKED OatMethodOffsets {
uint32_t code_offset_;
uint32_t frame_size_in_bytes_;
- uint32_t return_pc_offset_in_bytes_;
uint32_t core_spill_mask_;
uint32_t fp_spill_mask_;
uint32_t mapping_table_offset_;
diff --git a/src/oat_file.cc b/src/oat_file.cc
index 8af22b03c6..383bc2a6e2 100644
--- a/src/oat_file.cc
+++ b/src/oat_file.cc
@@ -175,7 +175,6 @@ const OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index)
return OatMethod(
GetOatPointer<const void*>(oat_method_offsets.code_offset_),
oat_method_offsets.frame_size_in_bytes_,
- oat_method_offsets.return_pc_offset_in_bytes_,
oat_method_offsets.core_spill_mask_,
oat_method_offsets.fp_spill_mask_,
GetOatPointer<const uint32_t*>(oat_method_offsets.mapping_table_offset_),
@@ -185,7 +184,6 @@ const OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index)
OatFile::OatMethod::OatMethod(const void* code,
const size_t frame_size_in_bytes,
- const size_t return_pc_offset_in_bytes,
const uint32_t core_spill_mask,
const uint32_t fp_spill_mask,
const uint32_t* mapping_table,
@@ -193,7 +191,6 @@ OatFile::OatMethod::OatMethod(const void* code,
const Method::InvokeStub* invoke_stub)
: code_(code),
frame_size_in_bytes_(frame_size_in_bytes),
- return_pc_offset_in_bytes_(return_pc_offset_in_bytes),
core_spill_mask_(core_spill_mask),
fp_spill_mask_(fp_spill_mask),
mapping_table_(mapping_table),
diff --git a/src/oat_file.h b/src/oat_file.h
index 1ee8c919c4..2c39e9d8b5 100644
--- a/src/oat_file.h
+++ b/src/oat_file.h
@@ -40,7 +40,6 @@ class OatFile {
// Create an OatMethod backed by an OatFile
OatMethod(const void* code,
const size_t frame_size_in_bytes,
- const size_t return_pc_offset_in_bytes,
const uint32_t core_spill_mask,
const uint32_t fp_spill_mask,
const uint32_t* mapping_table,
@@ -54,7 +53,6 @@ class OatFile {
const void* code_;
size_t frame_size_in_bytes_;
- size_t return_pc_offset_in_bytes_;
uint32_t core_spill_mask_;
uint32_t fp_spill_mask_;
const uint32_t* mapping_table_;
diff --git a/src/oat_test.cc b/src/oat_test.cc
index e90d2ede98..e3186de2ee 100644
--- a/src/oat_test.cc
+++ b/src/oat_test.cc
@@ -37,8 +37,11 @@ TEST_F(OatTest, WriteRead) {
for (size_t i = 0; i < dex_file.NumClassDefs(); i++) {
const DexFile::ClassDef& class_def = dex_file.GetClassDef(i);
const byte* class_data = dex_file.GetClassData(class_def);
- DexFile::ClassDataHeader header = dex_file.ReadClassDataHeader(&class_data);
- size_t num_virtual_methods = header.virtual_methods_size_;
+ size_t num_virtual_methods =0;
+ if (class_data != NULL) {
+ ClassDataItemIterator it(dex_file, class_data);
+ num_virtual_methods = it.NumVirtualMethods();
+ }
const char* descriptor = dex_file.GetClassDescriptor(class_def);
UniquePtr<const OatFile::OatClass> oat_class(oat_dex_file->GetOatClass(i));
@@ -49,12 +52,13 @@ TEST_F(OatTest, WriteRead) {
for (size_t i = 0; i < klass->NumDirectMethods(); i++, method_index++) {
Method* method = klass->GetDirectMethod(i);
const OatFile::OatMethod oat_method = oat_class->GetOatMethod(method_index);
- const CompiledMethod* compiled_method = compiler_->GetCompiledMethod(method);
+ const CompiledMethod* compiled_method =
+ compiler_->GetCompiledMethod(Compiler::MethodReference(&dex_file,
+ method->GetDexMethodIndex()));
if (compiled_method == NULL) {
EXPECT_TRUE(oat_method.code_ == NULL) << PrettyMethod(method) << " " << oat_method.code_;
EXPECT_EQ(oat_method.frame_size_in_bytes_, static_cast<uint32_t>(kStackAlignment));
- EXPECT_EQ(oat_method.return_pc_offset_in_bytes_, 0U);
EXPECT_EQ(oat_method.core_spill_mask_, 0U);
EXPECT_EQ(oat_method.fp_spill_mask_, 0U);
} else {
@@ -68,7 +72,6 @@ TEST_F(OatTest, WriteRead) {
<< PrettyMethod(method) << " " << code_size;
CHECK_EQ(0, memcmp(oat_code, &code[0], code_size));
EXPECT_EQ(oat_method.frame_size_in_bytes_, compiled_method->GetFrameSizeInBytes());
- EXPECT_EQ(oat_method.return_pc_offset_in_bytes_, compiled_method->GetReturnPcOffsetInBytes());
EXPECT_EQ(oat_method.core_spill_mask_, compiled_method->GetCoreSpillMask());
EXPECT_EQ(oat_method.fp_spill_mask_, compiled_method->GetFpSpillMask());
}
@@ -76,12 +79,13 @@ TEST_F(OatTest, WriteRead) {
for (size_t i = 0; i < num_virtual_methods; i++, method_index++) {
Method* method = klass->GetVirtualMethod(i);
const OatFile::OatMethod oat_method = oat_class->GetOatMethod(method_index);
- const CompiledMethod* compiled_method = compiler_->GetCompiledMethod(method);
+ const CompiledMethod* compiled_method =
+ compiler_->GetCompiledMethod(Compiler::MethodReference(&dex_file,
+ method->GetDexMethodIndex()));
if (compiled_method == NULL) {
EXPECT_TRUE(oat_method.code_ == NULL) << PrettyMethod(method) << " " << oat_method.code_;
EXPECT_EQ(oat_method.frame_size_in_bytes_, static_cast<uint32_t>(kStackAlignment));
- EXPECT_EQ(oat_method.return_pc_offset_in_bytes_, 0U);
EXPECT_EQ(oat_method.core_spill_mask_, 0U);
EXPECT_EQ(oat_method.fp_spill_mask_, 0U);
} else {
@@ -96,7 +100,6 @@ TEST_F(OatTest, WriteRead) {
<< PrettyMethod(method) << " " << code_size;
CHECK_EQ(0, memcmp(oat_code, &code[0], code_size));
EXPECT_EQ(oat_method.frame_size_in_bytes_, compiled_method->GetFrameSizeInBytes());
- EXPECT_EQ(oat_method.return_pc_offset_in_bytes_, compiled_method->GetReturnPcOffsetInBytes());
EXPECT_EQ(oat_method.core_spill_mask_, compiled_method->GetCoreSpillMask());
EXPECT_EQ(oat_method.fp_spill_mask_, compiled_method->GetFpSpillMask());
}
diff --git a/src/oat_writer.cc b/src/oat_writer.cc
index 664dcfe09c..f3e78e6250 100644
--- a/src/oat_writer.cc
+++ b/src/oat_writer.cc
@@ -24,6 +24,8 @@ OatWriter::OatWriter(const std::vector<const DexFile*>& dex_files,
compiler_ = &compiler;
class_loader_ = class_loader;
dex_files_ = &dex_files;
+ oat_header_ = NULL;
+ executable_offset_padding_length_ = 0;
size_t offset = InitOatHeader();
offset = InitOatDexFiles(offset);
@@ -36,6 +38,13 @@ OatWriter::OatWriter(const std::vector<const DexFile*>& dex_files,
CHECK_EQ(dex_files_->size(), oat_classes_.size());
}
+OatWriter::~OatWriter() {
+ delete oat_header_;
+ STLDeleteElements(&oat_dex_files_);
+ STLDeleteElements(&oat_classes_);
+ STLDeleteElements(&oat_methods_);
+}
+
size_t OatWriter::InitOatHeader() {
// create the OatHeader
oat_header_ = new OatHeader(dex_files_);
@@ -83,10 +92,13 @@ size_t OatWriter::InitOatMethods(size_t offset) {
oat_classes_[i]->methods_offsets_[class_def_index] = offset;
const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
const byte* class_data = dex_file->GetClassData(class_def);
- DexFile::ClassDataHeader header = dex_file->ReadClassDataHeader(&class_data);
- size_t num_direct_methods = header.direct_methods_size_;
- size_t num_virtual_methods = header.virtual_methods_size_;
- uint32_t num_methods = num_direct_methods + num_virtual_methods;
+ uint32_t num_methods = 0;
+ if (class_data != NULL) { // ie not an empty class, such as a marker interface
+ ClassDataItemIterator it(*dex_file, class_data);
+ size_t num_direct_methods = it.NumDirectMethods();
+ size_t num_virtual_methods = it.NumVirtualMethods();
+ num_methods = num_direct_methods + num_virtual_methods;
+ }
OatMethods* oat_methods = new OatMethods(num_methods);
oat_methods_.push_back(oat_methods);
offset += oat_methods->SizeOf();
@@ -135,46 +147,46 @@ size_t OatWriter::InitOatCodeClassDef(size_t offset,
const DexFile& dex_file,
const DexFile::ClassDef& class_def) {
const byte* class_data = dex_file.GetClassData(class_def);
- DexFile::ClassDataHeader header = dex_file.ReadClassDataHeader(&class_data);
- size_t num_virtual_methods = header.virtual_methods_size_;
- const char* descriptor = dex_file.GetClassDescriptor(class_def);
-
- // TODO: remove code ByteArrays from Class/Method (and therefore ClassLoader)
- // TODO: don't write code for shared stubs
- Class* klass = Runtime::Current()->GetClassLinker()->FindClass(descriptor, class_loader_);
- if (klass == NULL) {
- LOG(WARNING) << "Didn't find class '" << descriptor << "' in dex file " << dex_file.GetLocation();
- Thread* thread = Thread::Current();
- DCHECK(thread->IsExceptionPending());
- thread->ClearException();
+ if (class_data == NULL) {
+ // empty class, such as a marker interface
return offset;
}
- CHECK_EQ(klass->GetClassLoader(), class_loader_);
+ ClassDataItemIterator it(dex_file, class_data);
CHECK_EQ(oat_methods_[oat_class_index]->method_offsets_.size(),
- klass->NumDirectMethods() + num_virtual_methods);
- size_t class_def_method_index = 0;
- for (size_t i = 0; i < klass->NumDirectMethods(); i++, class_def_method_index++) {
- Method* method = klass->GetDirectMethod(i);
- CHECK(method != NULL) << descriptor << " direct " << i;
- offset = InitOatCodeMethod(offset, oat_class_index, class_def_method_index, method);
+ it.NumDirectMethods() + it.NumVirtualMethods());
+ // Skip fields
+ while (it.HasNextStaticField()) {
+ it.Next();
}
- // note that num_virtual_methods != klass->NumVirtualMethods() because of miranda methods
- for (size_t i = 0; i < num_virtual_methods; i++, class_def_method_index++) {
- Method* method = klass->GetVirtualMethod(i);
- CHECK(method != NULL) << descriptor << " virtual " << i;
- offset = InitOatCodeMethod(offset, oat_class_index, class_def_method_index, method);
+ while (it.HasNextInstanceField()) {
+ it.Next();
}
+ // Process methods
+ size_t class_def_method_index = 0;
+ while (it.HasNextDirectMethod()) {
+ bool is_static = (it.GetMemberAccessFlags() & kAccStatic) != 0;
+ offset = InitOatCodeMethod(offset, oat_class_index, class_def_method_index, is_static, true,
+ it.GetMemberIndex(), &dex_file);
+ class_def_method_index++;
+ it.Next();
+ }
+ while (it.HasNextVirtualMethod()) {
+ CHECK_EQ(it.GetMemberAccessFlags() & kAccStatic, 0U);
+ offset = InitOatCodeMethod(offset, oat_class_index, class_def_method_index, false, false,
+ it.GetMemberIndex(), &dex_file);
+ class_def_method_index++;
+ it.Next();
+ }
+ DCHECK(!it.HasNext());
return offset;
}
-size_t OatWriter::InitOatCodeMethod(size_t offset,
- size_t oat_class_index,
- size_t class_def_method_index,
- Method* method) {
+size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index,
+ size_t class_def_method_index, bool is_static, bool is_direct,
+ uint32_t method_idx, const DexFile* dex_file) {
// derived from CompiledMethod if available
uint32_t code_offset = 0;
uint32_t frame_size_in_bytes = kStackAlignment;
- uint32_t return_pc_offset_in_bytes = 0;
uint32_t core_spill_mask = 0;
uint32_t fp_spill_mask = 0;
uint32_t mapping_table_offset = 0;
@@ -182,7 +194,8 @@ size_t OatWriter::InitOatCodeMethod(size_t offset,
// derived from CompiledInvokeStub if available
uint32_t invoke_stub_offset = 0;
- const CompiledMethod* compiled_method = compiler_->GetCompiledMethod(method);
+ CompiledMethod* compiled_method =
+ compiler_->GetCompiledMethod(art::Compiler::MethodReference(dex_file, method_idx));
if (compiled_method != NULL) {
offset = compiled_method->AlignCode(offset);
DCHECK_ALIGNED(offset, kArmAlignment);
@@ -202,7 +215,6 @@ size_t OatWriter::InitOatCodeMethod(size_t offset,
}
frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
- return_pc_offset_in_bytes = compiled_method->GetReturnPcOffsetInBytes();
core_spill_mask = compiled_method->GetCoreSpillMask();
fp_spill_mask = compiled_method->GetFpSpillMask();
}
@@ -210,9 +222,6 @@ size_t OatWriter::InitOatCodeMethod(size_t offset,
offset += sizeof(frame_size_in_bytes);
oat_header_->UpdateChecksum(&frame_size_in_bytes, sizeof(frame_size_in_bytes));
- offset += sizeof(return_pc_offset_in_bytes);
- oat_header_->UpdateChecksum(&return_pc_offset_in_bytes, sizeof(return_pc_offset_in_bytes));
-
offset += sizeof(core_spill_mask);
oat_header_->UpdateChecksum(&core_spill_mask, sizeof(core_spill_mask));
@@ -249,7 +258,8 @@ size_t OatWriter::InitOatCodeMethod(size_t offset,
}
}
- const CompiledInvokeStub* compiled_invoke_stub = compiler_->GetCompiledInvokeStub(method);
+ const char* shorty = dex_file->GetMethodShorty(dex_file->GetMethodId(method_idx));
+ const CompiledInvokeStub* compiled_invoke_stub = compiler_->FindInvokeStub(is_static, shorty);
if (compiled_invoke_stub != NULL) {
offset = CompiledMethod::AlignCode(offset, compiler_->GetInstructionSet());
DCHECK_ALIGNED(offset, kArmAlignment);
@@ -271,22 +281,26 @@ size_t OatWriter::InitOatCodeMethod(size_t offset,
oat_methods_[oat_class_index]->method_offsets_[class_def_method_index]
= OatMethodOffsets(code_offset,
frame_size_in_bytes,
- return_pc_offset_in_bytes,
core_spill_mask,
fp_spill_mask,
mapping_table_offset,
vmap_table_offset,
invoke_stub_offset);
- // Note that we leave the offset and values back in the Method where ImageWriter will find them
- method->SetOatCodeOffset(code_offset);
- method->SetFrameSizeInBytes(frame_size_in_bytes);
- method->SetCoreSpillMask(core_spill_mask);
- method->SetFpSpillMask(fp_spill_mask);
- method->SetOatMappingTableOffset(mapping_table_offset);
- method->SetOatVmapTableOffset(vmap_table_offset);
- method->SetOatInvokeStubOffset(invoke_stub_offset);
-
+ if (compiler_->IsImage()) {
+ ClassLinker* linker = Runtime::Current()->GetClassLinker();
+ DexCache* dex_cache = linker->FindDexCache(*dex_file);
+ Method* method = linker->ResolveMethod(*dex_file, method_idx, dex_cache, class_loader_,
+ is_direct);
+ CHECK(method != NULL);
+ method->SetFrameSizeInBytes(frame_size_in_bytes);
+ method->SetCoreSpillMask(core_spill_mask);
+ method->SetFpSpillMask(fp_spill_mask);
+ method->SetOatMappingTableOffset(mapping_table_offset);
+ method->SetOatCodeOffset(code_offset);
+ method->SetOatVmapTableOffset(vmap_table_offset);
+ method->SetOatInvokeStubOffset(invoke_stub_offset);
+ }
return offset;
}
@@ -354,10 +368,11 @@ size_t OatWriter::WriteCode(File* file) {
}
size_t OatWriter::WriteCodeDexFiles(File* file, size_t code_offset) {
+ size_t oat_class_index = 0;
for (size_t i = 0; i != oat_classes_.size(); ++i) {
const DexFile* dex_file = (*dex_files_)[i];
CHECK(dex_file != NULL);
- code_offset = WriteCodeDexFile(file, code_offset, *dex_file);
+ code_offset = WriteCodeDexFile(file, code_offset, oat_class_index, *dex_file);
if (code_offset == 0) {
return 0;
}
@@ -365,10 +380,12 @@ size_t OatWriter::WriteCodeDexFiles(File* file, size_t code_offset) {
return code_offset;
}
-size_t OatWriter::WriteCodeDexFile(File* file, size_t code_offset, const DexFile& dex_file) {
- for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
+size_t OatWriter::WriteCodeDexFile(File* file, size_t code_offset, size_t& oat_class_index,
+ const DexFile& dex_file) {
+ for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs();
+ class_def_index++, oat_class_index++) {
const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
- code_offset = WriteCodeClassDef(file, code_offset, dex_file, class_def);
+ code_offset = WriteCodeClassDef(file, code_offset, oat_class_index, dex_file, class_def);
if (code_offset == 0) {
return 0;
}
@@ -376,54 +393,68 @@ size_t OatWriter::WriteCodeDexFile(File* file, size_t code_offset, const DexFile
return code_offset;
}
-void OatWriter::ReportWriteFailure(const char* what, Method* m, File* f) {
- PLOG(ERROR) << "Failed to write " << what << " for " << PrettyMethod(m) << " to " << f->name();
+void OatWriter::ReportWriteFailure(const char* what, uint32_t method_idx,
+ const DexFile& dex_file, File* f) const {
+ PLOG(ERROR) << "Failed to write " << what << " for " << PrettyMethod(method_idx, dex_file)
+ << " to " << f->name();
}
size_t OatWriter::WriteCodeClassDef(File* file,
- size_t code_offset,
+ size_t code_offset, size_t oat_class_index,
const DexFile& dex_file,
const DexFile::ClassDef& class_def) {
const byte* class_data = dex_file.GetClassData(class_def);
- DexFile::ClassDataHeader header = dex_file.ReadClassDataHeader(&class_data);
- size_t num_virtual_methods = header.virtual_methods_size_;
- const char* descriptor = dex_file.GetClassDescriptor(class_def);
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- Class* klass = class_linker->FindClass(descriptor, class_loader_);
- if (klass == NULL) {
- LOG(WARNING) << "Didn't find class '" << descriptor << "' in dex file " << dex_file.GetLocation();
- Thread* thread = Thread::Current();
- DCHECK(thread->IsExceptionPending());
- thread->ClearException();
+ if (class_data == NULL) {
+ // ie. an empty class such as a marker interface
return code_offset;
}
-
- // Note that we clear the code array here, image_writer will use GetCodeOffset to find it
- for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
- Method* method = klass->GetDirectMethod(i);
- code_offset = WriteCodeMethod(file, code_offset, method);
+ ClassDataItemIterator it(dex_file, class_data);
+ // Skip fields
+ while (it.HasNextStaticField()) {
+ it.Next();
+ }
+ while (it.HasNextInstanceField()) {
+ it.Next();
+ }
+ // Process methods
+ size_t class_def_method_index = 0;
+ while (it.HasNextDirectMethod()) {
+ bool is_static = (it.GetMemberAccessFlags() & kAccStatic) != 0;
+ code_offset = WriteCodeMethod(file, code_offset, oat_class_index, class_def_method_index,
+ is_static, it.GetMemberIndex(), dex_file);
if (code_offset == 0) {
return 0;
}
+ class_def_method_index++;
+ it.Next();
}
- // note that num_virtual_methods != klass->NumVirtualMethods() because of miranda methods
- for (size_t i = 0; i < num_virtual_methods; i++) {
- Method* method = klass->GetVirtualMethod(i);
- code_offset = WriteCodeMethod(file, code_offset, method);
+ while (it.HasNextVirtualMethod()) {
+ code_offset = WriteCodeMethod(file, code_offset, oat_class_index, class_def_method_index,
+ false, it.GetMemberIndex(), dex_file);
if (code_offset == 0) {
return 0;
}
- }
- for (size_t i = num_virtual_methods; i < klass->NumVirtualMethods(); i++) {
- Method* method = klass->GetVirtualMethod(i);
- CHECK(compiler_->GetCompiledMethod(method) == NULL) << PrettyMethod(method);
+ class_def_method_index++;
+ it.Next();
}
return code_offset;
}
-size_t OatWriter::WriteCodeMethod(File* file, size_t code_offset, Method* method) {
- const CompiledMethod* compiled_method = compiler_->GetCompiledMethod(method);
- if (compiled_method != NULL) {
+size_t OatWriter::WriteCodeMethod(File* file, size_t code_offset, size_t oat_class_index,
+ size_t class_def_method_index, bool is_static,
+ uint32_t method_idx, const DexFile& dex_file) {
+ const CompiledMethod* compiled_method =
+ compiler_->GetCompiledMethod(art::Compiler::MethodReference(&dex_file, method_idx));
+
+ uint32_t frame_size_in_bytes = 0;
+ uint32_t core_spill_mask = 0;
+ uint32_t fp_spill_mask = 0;
+
+ OatMethodOffsets method_offsets =
+ oat_methods_[oat_class_index]->method_offsets_[class_def_method_index];
+
+
+ if (compiled_method != NULL) { // ie. not an abstract method
uint32_t aligned_code_offset = compiled_method->AlignCode(code_offset);
uint32_t aligned_code_delta = aligned_code_offset - code_offset;
if (aligned_code_delta != 0) {
@@ -443,42 +474,38 @@ size_t OatWriter::WriteCodeMethod(File* file, size_t code_offset, Method* method
// Deduplicate code arrays
size_t offset = code_offset + compiled_method->CodeDelta();
std::map<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code);
- if (code_iter != code_offsets_.end() && offset != method->GetOatCodeOffset()) {
- DCHECK((code_size == 0 && method->GetOatCodeOffset() == 0)
- || code_iter->second == method->GetOatCodeOffset()) << PrettyMethod(method);
+ if (code_iter != code_offsets_.end() && offset != method_offsets.code_offset_) {
+ DCHECK((code_size == 0 && method_offsets.code_offset_ == 0)
+ || code_iter->second == method_offsets.code_offset_)
+ << PrettyMethod(method_idx, dex_file);
} else {
- DCHECK((code_size == 0 && method->GetOatCodeOffset() == 0)
- || offset == method->GetOatCodeOffset()) << PrettyMethod(method);
+ DCHECK((code_size == 0 && method_offsets.code_offset_ == 0)
+ || offset == method_offsets.code_offset_)
+ << PrettyMethod(method_idx, dex_file);
if (!file->WriteFully(&code[0], code_size)) {
- ReportWriteFailure("method code", method, file);
+ ReportWriteFailure("method code", method_idx, dex_file, file);
return false;
}
code_offset += code_size;
}
DCHECK_CODE_OFFSET();
+ frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
+ core_spill_mask = compiled_method->GetCoreSpillMask();
+ fp_spill_mask = compiled_method->GetFpSpillMask();
}
- uint32_t frame_size_in_bytes = method->GetFrameSizeInBytes();
- uint32_t return_pc_offset_in_bytes = method->GetReturnPcOffsetInBytes();
- uint32_t core_spill_mask = method->GetCoreSpillMask();
- uint32_t fp_spill_mask = method->GetFpSpillMask();
if (!file->WriteFully(&frame_size_in_bytes, sizeof(frame_size_in_bytes))) {
- ReportWriteFailure("method frame size", method, file);
+ ReportWriteFailure("method frame size", method_idx, dex_file, file);
return false;
}
code_offset += sizeof(frame_size_in_bytes);
- if (!file->WriteFully(&return_pc_offset_in_bytes, sizeof(return_pc_offset_in_bytes))) {
- ReportWriteFailure("method return pc", method, file);
- return false;
- }
- code_offset += sizeof(return_pc_offset_in_bytes);
if (!file->WriteFully(&core_spill_mask, sizeof(core_spill_mask))) {
- ReportWriteFailure("method core spill mask", method, file);
+ ReportWriteFailure("method core spill mask", method_idx, dex_file, file);
return false;
}
code_offset += sizeof(core_spill_mask);
if (!file->WriteFully(&fp_spill_mask, sizeof(fp_spill_mask))) {
- ReportWriteFailure("method fp spill mask", method, file);
+ ReportWriteFailure("method fp spill mask", method_idx, dex_file, file);
return false;
}
code_offset += sizeof(fp_spill_mask);
@@ -488,15 +515,19 @@ size_t OatWriter::WriteCodeMethod(File* file, size_t code_offset, Method* method
size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]);
// Deduplicate mapping tables
- std::map<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter = mapping_table_offsets_.find(&mapping_table);
- if (mapping_iter != mapping_table_offsets_.end() && code_offset != method->GetOatMappingTableOffset()) {
- DCHECK((mapping_table_size == 0 && method->GetOatMappingTableOffset() == 0)
- || mapping_iter->second == method->GetOatMappingTableOffset()) << PrettyMethod(method);
+ std::map<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter =
+ mapping_table_offsets_.find(&mapping_table);
+ if (mapping_iter != mapping_table_offsets_.end() &&
+ code_offset != method_offsets.mapping_table_offset_) {
+ DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0)
+ || mapping_iter->second == method_offsets.mapping_table_offset_)
+ << PrettyMethod(method_idx, dex_file);
} else {
- DCHECK((mapping_table_size == 0 && method->GetOatMappingTableOffset() == 0)
- || code_offset == method->GetOatMappingTableOffset()) << PrettyMethod(method);
+ DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0)
+ || code_offset == method_offsets.mapping_table_offset_)
+ << PrettyMethod(method_idx, dex_file);
if (!file->WriteFully(&mapping_table[0], mapping_table_size)) {
- ReportWriteFailure("mapping table", method, file);
+ ReportWriteFailure("mapping table", method_idx, dex_file, file);
return false;
}
code_offset += mapping_table_size;
@@ -507,23 +538,27 @@ size_t OatWriter::WriteCodeMethod(File* file, size_t code_offset, Method* method
size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]);
// Deduplicate vmap tables
- std::map<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter = vmap_table_offsets_.find(&vmap_table);
- if (vmap_iter != vmap_table_offsets_.end() && code_offset != method->GetOatVmapTableOffset()) {
- DCHECK((vmap_table_size == 0 && method->GetOatVmapTableOffset() == 0)
- || vmap_iter->second == method->GetOatVmapTableOffset()) << PrettyMethod(method);
+ std::map<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter =
+ vmap_table_offsets_.find(&vmap_table);
+ if (vmap_iter != vmap_table_offsets_.end() &&
+ code_offset != method_offsets.vmap_table_offset_) {
+ DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0)
+ || vmap_iter->second == method_offsets.vmap_table_offset_)
+ << PrettyMethod(method_idx, dex_file);
} else {
- DCHECK((vmap_table_size == 0 && method->GetOatVmapTableOffset() == 0)
- || code_offset == method->GetOatVmapTableOffset()) << PrettyMethod(method);
+ DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0)
+ || code_offset == method_offsets.vmap_table_offset_)
+ << PrettyMethod(method_idx, dex_file);
if (!file->WriteFully(&vmap_table[0], vmap_table_size)) {
- ReportWriteFailure("vmap table", method, file);
+ ReportWriteFailure("vmap table", method_idx, dex_file, file);
return false;
}
code_offset += vmap_table_size;
}
DCHECK_CODE_OFFSET();
}
-
- const CompiledInvokeStub* compiled_invoke_stub = compiler_->GetCompiledInvokeStub(method);
+ const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
+ const CompiledInvokeStub* compiled_invoke_stub = compiler_->FindInvokeStub(is_static, shorty);
if (compiled_invoke_stub != NULL) {
uint32_t aligned_code_offset = CompiledMethod::AlignCode(code_offset,
compiler_->GetInstructionSet());
@@ -543,37 +578,34 @@ size_t OatWriter::WriteCodeMethod(File* file, size_t code_offset, Method* method
size_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]);
// Deduplicate invoke stubs
- std::map<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter = code_offsets_.find(&invoke_stub);
- if (stub_iter != code_offsets_.end() && code_offset != method->GetOatInvokeStubOffset()) {
- DCHECK((invoke_stub_size == 0 && method->GetOatInvokeStubOffset() == 0)
- || stub_iter->second == method->GetOatInvokeStubOffset()) << PrettyMethod(method);
+ std::map<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter =
+ code_offsets_.find(&invoke_stub);
+ if (stub_iter != code_offsets_.end() &&
+ code_offset != method_offsets.invoke_stub_offset_) {
+ DCHECK((invoke_stub_size == 0 && method_offsets.invoke_stub_offset_ == 0)
+ || stub_iter->second == method_offsets.invoke_stub_offset_)
+ << PrettyMethod(method_idx, dex_file);
} else {
- DCHECK((invoke_stub_size == 0 && method->GetOatInvokeStubOffset() == 0)
- || code_offset == method->GetOatInvokeStubOffset()) << PrettyMethod(method);
+ DCHECK((invoke_stub_size == 0 && method_offsets.invoke_stub_offset_ == 0)
+ || code_offset == method_offsets.invoke_stub_offset_)
+ << PrettyMethod(method_idx, dex_file);
if (!file->WriteFully(&invoke_stub[0], invoke_stub_size)) {
- ReportWriteFailure("invoke stub code", method, file);
+ ReportWriteFailure("invoke stub code", method_idx, dex_file, file);
return false;
}
code_offset += invoke_stub_size;
}
DCHECK_CODE_OFFSET();
}
-
return code_offset;
}
-OatWriter::~OatWriter() {
- delete oat_header_;
- STLDeleteElements(&oat_dex_files_);
- STLDeleteElements(&oat_classes_);
- STLDeleteElements(&oat_methods_);
-}
-
OatWriter::OatDexFile::OatDexFile(const DexFile& dex_file) {
const std::string& location = dex_file.GetLocation();
dex_file_location_size_ = location.size();
dex_file_location_data_ = reinterpret_cast<const uint8_t*>(location.data());
dex_file_checksum_ = dex_file.GetHeader().checksum_;
+ classes_offset_ = 0;
}
size_t OatWriter::OatDexFile::SizeOf() const {
diff --git a/src/oat_writer.h b/src/oat_writer.h
index 0642fa4d5c..97cdb50ec0 100644
--- a/src/oat_writer.h
+++ b/src/oat_writer.h
@@ -71,28 +71,23 @@ class OatWriter {
size_t oat_class_index,
const DexFile& dex_file,
const DexFile::ClassDef& class_def);
- size_t InitOatCodeMethod(size_t offset,
- size_t oat_class_index,
- size_t class_def_method_index,
- Method* method);
+ size_t InitOatCodeMethod(size_t offset, size_t oat_class_index, size_t class_def_method_index,
+ bool is_static, bool is_direct, uint32_t method_idx, const DexFile*);
bool Write(File* file);
bool WriteTables(File* file);
size_t WriteCode(File* file);
- size_t WriteCodeDexFiles(File* file,
- size_t offset);
- size_t WriteCodeDexFile(File* file,
- size_t offset,
+ size_t WriteCodeDexFiles(File* file, size_t offset);
+ size_t WriteCodeDexFile(File* file, size_t offset, size_t& oat_class_index,
const DexFile& dex_file);
- size_t WriteCodeClassDef(File* file,
- size_t offset,
- const DexFile& dex_file,
- const DexFile::ClassDef& class_def);
- size_t WriteCodeMethod(File* file,
- size_t offset,
- Method* method);
-
- void ReportWriteFailure(const char* what, Method* m, File* f);
+ size_t WriteCodeClassDef(File* file, size_t offset, size_t oat_class_index,
+ const DexFile& dex_file, const DexFile::ClassDef& class_def);
+ size_t WriteCodeMethod(File* file, size_t offset, size_t oat_class_index,
+ size_t class_def_method_index, bool is_static, uint32_t method_idx,
+ const DexFile& dex_file);
+
+ void ReportWriteFailure(const char* what, uint32_t method_idx, const DexFile& dex_file,
+ File* f) const;
class OatDexFile {
public:
diff --git a/src/oatdump.cc b/src/oatdump.cc
index 61f352e41c..8b0ada4fa1 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -136,47 +136,33 @@ class OatDump {
const DexFile& dex_file,
const DexFile::ClassDef& class_def) {
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_;
- uint32_t method_index = 0;
+ if (class_data == NULL) { // empty class such as a marker interface?
+ return;
+ }
+ ClassDataItemIterator it(dex_file, class_data);
// just skipping through the fields to advance class_data
- 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);
- }
+ while (it.HasNextStaticField()) {
+ 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);
- }
+ while (it.HasNextInstanceField()) {
+ it.Next();
}
- if (num_direct_methods != 0) {
- uint32_t last_idx = 0;
- for (size_t i = 0; i < num_direct_methods; ++i, method_index++) {
- DexFile::Method dex_method;
- dex_file.dexReadClassDataMethod(&class_data, &dex_method, &last_idx);
- const OatFile::OatMethod oat_method = oat_class.GetOatMethod(method_index);
- DumpOatMethod(os, method_index, oat_file, oat_method, dex_file, dex_method);
- }
+ uint32_t method_index = 0;
+ while (it.HasNextDirectMethod()) {
+ const OatFile::OatMethod oat_method = oat_class.GetOatMethod(method_index);
+ DumpOatMethod(os, method_index, oat_file, oat_method, dex_file, it.GetMemberIndex());
+ method_index++;
+ it.Next();
}
- if (num_virtual_methods != 0) {
- uint32_t last_idx = 0;
- for (size_t i = 0; i < num_virtual_methods; ++i, method_index++) {
- DexFile::Method dex_method;
- dex_file.dexReadClassDataMethod(&class_data, &dex_method, &last_idx);
- const OatFile::OatMethod oat_method = oat_class.GetOatMethod(method_index);
- DumpOatMethod(os, method_index, oat_file, oat_method, dex_file, dex_method);
- }
+ while (it.HasNextVirtualMethod()) {
+ const OatFile::OatMethod oat_method = oat_class.GetOatMethod(method_index);
+ DumpOatMethod(os, method_index, oat_file, oat_method, dex_file, it.GetMemberIndex());
+ method_index++;
+ it.Next();
}
+ DCHECK(!it.HasNext());
os << std::flush;
}
static void DumpOatMethod(std::ostream& os,
@@ -184,19 +170,17 @@ class OatDump {
const OatFile& oat_file,
const OatFile::OatMethod& oat_method,
const DexFile& dex_file,
- const DexFile::Method& dex_method) {
- const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method.method_idx_);
+ uint32_t method_idx) {
+ const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
const char* name = dex_file.GetMethodName(method_id);
std::string signature = dex_file.GetMethodSignature(method_id);
os << StringPrintf("\t%d: %s %s (method_idx=%d)\n",
- method_index, name, signature.c_str(), dex_method.method_idx_);
+ method_index, name, signature.c_str(), method_idx);
os << StringPrintf("\t\tcode: %p (offset=%08x)\n",
oat_method.code_,
reinterpret_cast<const byte*>(oat_method.code_) - oat_file.GetBase());
os << StringPrintf("\t\tframe_size_in_bytes: %d\n",
oat_method.frame_size_in_bytes_);
- os << StringPrintf("\t\treturn_pc_offset_in_bytes: %d\n",
- oat_method.return_pc_offset_in_bytes_);
os << StringPrintf("\t\tcore_spill_mask: %08x\n",
oat_method.core_spill_mask_);
os << StringPrintf("\t\tfp_spill_mask: %08x\n",
diff --git a/src/object.cc b/src/object.cc
index 9cc0e3add6..3954b3df2c 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -20,6 +20,7 @@
#include "monitor.h"
#include "runtime.h"
#include "stack.h"
+#include "utils.h"
namespace art {
@@ -122,7 +123,7 @@ size_t Field::PrimitiveSize() const {
const char* Field::GetTypeDescriptor() const {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
const DexFile& dex_file = class_linker->FindDexFile(GetDeclaringClass()->GetDexCache());
- const char* descriptor = dex_file.dexStringByTypeIdx(GetTypeIdx());
+ const char* descriptor = dex_file.StringByTypeIdx(GetTypeIdx());
DCHECK(descriptor != NULL);
return descriptor;
}
@@ -136,6 +137,15 @@ Class* Field::GetType() {
return type;
}
+void Field::SetOffset(MemberOffset num_bytes) {
+ DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
+ Primitive::Type type = GetPrimitiveType();
+ if (type == Primitive::kPrimDouble || type == Primitive::kPrimLong) {
+ DCHECK_ALIGNED(num_bytes.Uint32Value(), 8);
+ }
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Field, offset_), num_bytes.Uint32Value(), false);
+}
+
void Field::InitJavaFields() {
Thread* self = Thread::Current();
ScopedThreadStateChange tsc(self, Thread::kRunnable);
@@ -405,12 +415,43 @@ void Method::SetReturnTypeIdx(uint32_t new_return_type_idx) {
new_return_type_idx, false);
}
+uint32_t Method::GetDexMethodIndex() const {
+ // TODO: add the method index to Method - which will also mean a number of Method fields can
+ // become dex file lookups (which will then mean we may want faster access to the dex file)
+ // Find the dex file
+ const DexCache* dex_cache = GetDeclaringClass()->GetDexCache();
+ const DexFile& dex_file = Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache);
+ // Find the class_def in the dex file
+ uint32_t class_def_idx;
+ bool found_class_def =
+ dex_file.FindClassDefIndex(GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8(),
+ class_def_idx);
+ CHECK(found_class_def);
+ const DexFile::TypeId& type_id =
+ dex_file.GetTypeId(dex_file.GetClassDef(class_def_idx).class_idx_);
+ const DexFile::StringId* name_str_id = dex_file.FindStringId(GetName()->ToModifiedUtf8());
+ CHECK(name_str_id != NULL); // Failed to find method's name?
+ uint16_t return_type_idx;
+ std::vector<uint16_t> param_type_idxs;
+ std::string signature = GetSignature()->ToModifiedUtf8();
+ bool found_type_list = dex_file.CreateTypeList(&return_type_idx, &param_type_idxs, signature);
+ CHECK(found_type_list); // Failed to parse signature
+ const DexFile::ProtoId* sig_proto_id = dex_file.FindProtoId(return_type_idx, param_type_idxs);
+ CHECK(sig_proto_id != NULL); // Failed to find method's prototype
+ const DexFile::MethodId* method_id =
+ dex_file.FindMethodId(type_id, *name_str_id, *sig_proto_id);
+ CHECK(method_id != NULL); // Failed to find method?
+ uint32_t method_idx = dex_file.GetIndexForMethodId(*method_id);
+ DCHECK_EQ(PrettyMethod(method_idx, dex_file), PrettyMethod(this));
+ return method_idx;
+}
+
const char* Method::GetReturnTypeDescriptor() const {
Class* declaring_class = GetDeclaringClass();
DexCache* dex_cache = declaring_class->GetDexCache();
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
- const char* descriptor = dex_file.dexStringByTypeIdx(GetReturnTypeIdx());
+ const char* descriptor = dex_file.StringByTypeIdx(GetReturnTypeIdx());
DCHECK(descriptor != NULL);
return descriptor;
}
@@ -504,24 +545,6 @@ size_t Method::NumArgRegisters(const StringPiece& shorty) {
return num_registers;
}
-size_t Method::NumArgArrayBytes() const {
- const String* shorty = GetShorty();
- size_t num_bytes = 0;
- for (int i = 1; i < shorty->GetLength(); ++i) {
- char ch = shorty->CharAt(i);
- if (ch == 'D' || ch == 'J') {
- num_bytes += 8;
- } else if (ch == 'L') {
- // Argument is a reference or an array. The shorty descriptor
- // does not distinguish between these types.
- num_bytes += sizeof(Object*);
- } else {
- num_bytes += 4;
- }
- }
- return num_bytes;
-}
-
size_t Method::NumArgs() const {
// "1 +" because the first in Args is the receiver.
// "- 1" because we don't count the return type.
@@ -677,12 +700,11 @@ uint32_t Method::FindCatchBlock(Class* exception_type, uint32_t dex_pc) const {
const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
const DexFile::CodeItem* code_item = dex_file.GetCodeItem(GetCodeItemOffset());
// Iterate over the catch handlers associated with dex_pc
- for (DexFile::CatchHandlerIterator iter = dex_file.dexFindCatchHandler(*code_item, dex_pc);
- !iter.HasNext(); iter.Next()) {
- uint32_t iter_type_idx = iter.Get().type_idx_;
+ for (CatchHandlerIterator it(*code_item, dex_pc); it.HasNext(); it.Next()) {
+ uint16_t iter_type_idx = it.GetHandlerTypeIndex();
// Catch all case
- if (iter_type_idx == DexFile::kDexNoIndex) {
- return iter.Get().address_;
+ if (iter_type_idx == DexFile::kDexNoIndex16) {
+ return it.GetHandlerAddress();
}
// Does this catch exception type apply?
Class* iter_exception_type = dex_cache->GetResolvedType(iter_type_idx);
@@ -691,7 +713,7 @@ uint32_t Method::FindCatchBlock(Class* exception_type, uint32_t dex_pc) const {
LOG(WARNING) << "Unresolved exception class when finding catch block: "
<< dex_file.GetTypeDescriptor(dex_file.GetTypeId(iter_type_idx));
} else if (iter_exception_type->IsAssignableFrom(exception_type)) {
- return iter.Get().address_;
+ return it.GetHandlerAddress();
}
}
// Handler not found
@@ -778,6 +800,11 @@ Object* Class::AllocObject() {
return Heap::AllocObject(this, this->object_size_);
}
+void Class::SetClassSize(size_t new_class_size) {
+ DCHECK_GE(new_class_size, GetClassSize()) << " class=" << PrettyTypeOf(this);
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), new_class_size, false);
+}
+
void Class::DumpClass(std::ostream& os, int flags) const {
if ((flags & kDumpClassFullDetail) == 0) {
os << PrettyClass(this);
diff --git a/src/object.h b/src/object.h
index dd2c1ca6e8..6a91970c74 100644
--- a/src/object.h
+++ b/src/object.h
@@ -619,6 +619,8 @@ class MANAGED Method : public AccessibleObject {
return (GetAccessFlags() & kAccSynthetic) != 0;
}
+ uint32_t GetDexMethodIndex() const;
+
uint16_t GetMethodIndex() const;
size_t GetVtableIndex() const {
@@ -644,10 +646,6 @@ class MANAGED Method : public AccessibleObject {
// Number of 32bit registers that would be required to hold all the arguments
static size_t NumArgRegisters(const StringPiece& shorty);
- // Number of argument bytes required for densely packing the
- // arguments into an array of arguments.
- size_t NumArgArrayBytes() const;
-
uint16_t NumRegisters() const;
void SetNumRegisters(uint16_t new_num_registers) {
@@ -1088,7 +1086,8 @@ class MANAGED Method : public AccessibleObject {
// Native invocation stub entry point for calling from native to managed code.
const InvokeStub* invoke_stub_;
- // Index of the return type
+ // Index of the return type in the declaring classes dex cache or dex file's type ids
+ // TODO: value is really just 16bit
uint32_t java_return_type_idx_;
// Mapping from native pc to dex pc
@@ -1498,10 +1497,7 @@ class MANAGED Class : public StaticStorageBase {
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), false);
}
- void SetClassSize(size_t new_class_size) {
- DCHECK_GE(new_class_size, GetClassSize()) << " class=" << PrettyTypeOf(this);
- SetField32(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), new_class_size, false);
- }
+ void SetClassSize(size_t new_class_size);
size_t GetObjectSize() const {
CHECK(!IsVariableSize()) << " class=" << PrettyTypeOf(this);
@@ -2092,9 +2088,11 @@ class MANAGED Class : public StaticStorageBase {
// Set in LoadClass, used to LinkClass
// see also super_class_
+ // TODO: really 16bits
uint32_t super_class_type_idx_;
// type index from dex file
+ // TODO: really 16bits
uint32_t type_idx_;
// TODO: ?
@@ -2199,15 +2197,6 @@ inline size_t Object::SizeOf() const {
return result;
}
-inline void Field::SetOffset(MemberOffset num_bytes) {
- DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
- Primitive::Type type = GetPrimitiveType();
- if (type == Primitive::kPrimDouble || type == Primitive::kPrimLong) {
- DCHECK_ALIGNED(num_bytes.Uint32Value(), 8);
- }
- SetField32(OFFSET_OF_OBJECT_MEMBER(Field, offset_), num_bytes.Uint32Value(), false);
-}
-
inline Class* Field::GetDeclaringClass() const {
Class* result = GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Field, declaring_class_), false);
DCHECK(result != NULL);
@@ -2480,6 +2469,9 @@ class MANAGED String : public Object {
bool Equals(const String* that) const;
+ // Compare UTF-16 code point values not in a locale-sensitive manner
+ int Compare(int32_t utf16_length, const char* utf8_data_in);
+
// TODO: do we need this overload? give it a more intention-revealing name.
bool Equals(const uint16_t* that_chars, int32_t that_offset,
int32_t that_length) const;
@@ -2615,7 +2607,7 @@ inline uint32_t Class::GetAccessFlags() const {
this == String::GetJavaLangString() ||
this == Field::GetJavaLangReflectField() ||
this == Method::GetConstructorClass() ||
- this == Method::GetMethodClass()) << PrettyClass(this);
+ this == Method::GetMethodClass());
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), false);
}
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 7ae5da572b..e6011daba9 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -49,7 +49,7 @@ extern "C" uint32_t artObjectInitFromCode(Object* o, Thread* self, Method** sp)
/*
* NOTE: once debugger/profiler support is added, we'll need to check
* here and branch to actual compiled object.<init> to handle any
- * breakpoint/logging activites if either is active.
+ * breakpoint/logging activities if either is active.
*/
return self->IsExceptionPending() ? -1 : 0;
}
@@ -163,7 +163,7 @@ static std::string ClassNameFromIndex(Method* method, uint32_t ref,
CHECK(false) << static_cast<int>(ref_type);
}
- std::string class_name(PrettyDescriptor(dex_file.dexStringByTypeIdx(type_idx)));
+ std::string class_name(PrettyDescriptor(dex_file.StringByTypeIdx(type_idx)));
if (!access) {
return class_name;
}
@@ -185,7 +185,7 @@ static std::string FieldNameFromIndex(const Method* method, uint32_t ref,
const DexFile::FieldId& id = dex_file.GetFieldId(ref);
std::string class_name(PrettyDescriptor(dex_file.GetFieldDeclaringClassDescriptor(id)));
- const char* field_name = dex_file.dexStringById(id.name_idx_);
+ const char* field_name = dex_file.StringDataByIdx(id.name_idx_);
if (!access) {
return class_name + "." + field_name;
}
@@ -207,7 +207,7 @@ static std::string MethodNameFromIndex(const Method* method, uint32_t ref,
const DexFile::MethodId& id = dex_file.GetMethodId(ref);
std::string class_name(PrettyDescriptor(dex_file.GetMethodDeclaringClassDescriptor(id)));
- const char* method_name = dex_file.dexStringById(id.name_idx_);
+ const char* method_name = dex_file.StringDataByIdx(id.name_idx_);
if (!access) {
return class_name + "." + method_name;
}
@@ -215,7 +215,7 @@ static std::string MethodNameFromIndex(const Method* method, uint32_t ref,
std::string result;
result += "tried to access method ";
result += class_name + "." + method_name + ":" +
- dex_file.CreateMethodDescriptor(id.proto_idx_, NULL);
+ dex_file.CreateMethodSignature(id.proto_idx_, NULL);
result += " from class ";
result += PrettyDescriptor(method->GetDeclaringClass()->GetDescriptor());
return result;
diff --git a/src/utf.cc b/src/utf.cc
index 31fbe97da0..52f03a95a1 100644
--- a/src/utf.cc
+++ b/src/utf.cc
@@ -87,6 +87,20 @@ uint16_t GetUtf16FromUtf8(const char** utf8_data_in) {
return ((one & 0x0f) << 12) | ((two & 0x3f) << 6) | (three & 0x3f);
}
+int CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(const char* utf8_1, const char* utf8_2) {
+ for (;;) {
+ uint16_t c1 = GetUtf16FromUtf8(&utf8_1);
+ uint16_t c2 = GetUtf16FromUtf8(&utf8_2);
+ if (c1 == 0) {
+ return (c2 == 0) ? 0 : -1;
+ } else if (c2 == 0) {
+ return 1;
+ } else if (c1 != c2) {
+ return c1 > c2 ? 1 : -1;
+ }
+ }
+}
+
size_t CountUtf8Bytes(const uint16_t* chars, size_t char_count) {
size_t result = 0;
while (char_count--) {
diff --git a/src/utf.h b/src/utf.h
index 7b9b90e11e..42c6dc706b 100644
--- a/src/utf.h
+++ b/src/utf.h
@@ -34,6 +34,11 @@ size_t CountUtf8Bytes(const uint16_t* chars, size_t char_count);
void ConvertModifiedUtf8ToUtf16(uint16_t* utf16_out, const char* utf8_in);
/*
+ * Compare two modified UTF-8 strings as UTF-16 code point values in a non-locale sensitive manner
+ */
+int CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(const char* utf8_1, const char* utf8_2);
+
+/*
* Convert from UTF-16 to Modified UTF-8. Note that the output is _not_
* NUL-terminated. You probably need to call CountUtf8Bytes before calling
* this anyway, so if you want a NUL-terminated string, you know where to
diff --git a/src/utils.cc b/src/utils.cc
index c37343ce74..c528f1ca10 100644
--- a/src/utils.cc
+++ b/src/utils.cc
@@ -153,6 +153,19 @@ std::string PrettyMethod(const Method* m, bool with_signature) {
return result;
}
+std::string PrettyMethod(uint32_t method_idx, const DexFile& dex_file, bool with_signature) {
+ const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
+ std::string result(PrettyDescriptor(dex_file.GetMethodDeclaringClassDescriptor(method_id)));
+ result += '.';
+ result += dex_file.GetMethodName(method_id);
+ if (with_signature) {
+ // TODO: iterate over the signature's elements and pass them all to
+ // PrettyDescriptor? We'd need to pull out the return type specially, too.
+ result += dex_file.GetMethodSignature(method_id);
+ }
+ return result;
+}
+
std::string PrettyTypeOf(const Object* obj) {
if (obj == NULL) {
return "null";
diff --git a/src/utils.h b/src/utils.h
index f747ae82e1..f5e0c490fb 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -16,6 +16,7 @@
namespace art {
class Class;
+class DexFile;
class Field;
class Method;
class Object;
@@ -166,6 +167,7 @@ std::string PrettyField(const Field* f, bool with_type = true);
// Returns a human-readable signature for 'm'. Something like "a.b.C.m" or
// "a.b.C.m(II)V" (depending on the value of 'with_signature').
std::string PrettyMethod(const Method* m, bool with_signature = true);
+std::string PrettyMethod(uint32_t method_idx, const DexFile& dex_file, bool with_signature = true);
// Returns a human-readable form of the name of the *class* of the given object.
// So given an instance of java.lang.String, the output would
diff --git a/test/CreateMethodDescriptor/CreateMethodDescriptor.java b/test/CreateMethodSignature/CreateMethodSignature.java
index aa1f3de309..32338f1779 100644
--- a/test/CreateMethodDescriptor/CreateMethodDescriptor.java
+++ b/test/CreateMethodSignature/CreateMethodSignature.java
@@ -1,6 +1,6 @@
// Copyright 2011 Google Inc. All Rights Reserved.
-class CreateMethodDescriptor {
+class CreateMethodSignature {
Float m1(int a, double b, long c, Object d) { return null; }
- CreateMethodDescriptor m2(boolean x, short y, char z) { return null; }
+ CreateMethodSignature m2(boolean x, short y, char z) { return null; }
}