summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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; }
}