summaryrefslogtreecommitdiff
path: root/src/class_linker.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/class_linker.cc')
-rw-r--r--src/class_linker.cc231
1 files changed, 79 insertions, 152 deletions
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()) {