summaryrefslogtreecommitdiffstats
path: root/runtime/class_linker.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r--runtime/class_linker.cc290
1 files changed, 149 insertions, 141 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index d6ac3bad52..095272394a 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -56,7 +56,6 @@
#include "compiler_callbacks.h"
#include "debug_print.h"
#include "debugger.h"
-#include "dex/class_accessor-inl.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_exception_helpers.h"
@@ -2735,50 +2734,52 @@ mirror::Class* ClassLinker::DefineClass(Thread* self,
uint32_t ClassLinker::SizeOfClassWithoutEmbeddedTables(const DexFile& dex_file,
const DexFile::ClassDef& dex_class_def) {
+ const uint8_t* class_data = dex_file.GetClassData(dex_class_def);
size_t num_ref = 0;
size_t num_8 = 0;
size_t num_16 = 0;
size_t num_32 = 0;
size_t num_64 = 0;
- ClassAccessor accessor(dex_file, dex_class_def);
- // We allow duplicate definitions of the same field in a class_data_item
- // but ignore the repeated indexes here, b/21868015.
- uint32_t last_field_idx = dex::kDexNoIndex;
- for (const ClassAccessor::Field& field : accessor.GetStaticFields()) {
- uint32_t field_idx = field.GetIndex();
- // Ordering enforced by DexFileVerifier.
- DCHECK(last_field_idx == dex::kDexNoIndex || last_field_idx <= field_idx);
- if (UNLIKELY(field_idx == last_field_idx)) {
- continue;
- }
- last_field_idx = field_idx;
- const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx);
- const char* descriptor = dex_file.GetFieldTypeDescriptor(field_id);
- char c = descriptor[0];
- switch (c) {
- case 'L':
- case '[':
- num_ref++;
- break;
- case 'J':
- case 'D':
- num_64++;
- break;
- case 'I':
- case 'F':
- num_32++;
- break;
- case 'S':
- case 'C':
- num_16++;
- break;
- case 'B':
- case 'Z':
- num_8++;
- break;
- default:
- LOG(FATAL) << "Unknown descriptor: " << c;
- UNREACHABLE();
+ if (class_data != nullptr) {
+ // We allow duplicate definitions of the same field in a class_data_item
+ // but ignore the repeated indexes here, b/21868015.
+ uint32_t last_field_idx = dex::kDexNoIndex;
+ for (ClassDataItemIterator it(dex_file, class_data); it.HasNextStaticField(); it.Next()) {
+ uint32_t field_idx = it.GetMemberIndex();
+ // Ordering enforced by DexFileVerifier.
+ DCHECK(last_field_idx == dex::kDexNoIndex || last_field_idx <= field_idx);
+ if (UNLIKELY(field_idx == last_field_idx)) {
+ continue;
+ }
+ last_field_idx = field_idx;
+ const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx);
+ const char* descriptor = dex_file.GetFieldTypeDescriptor(field_id);
+ char c = descriptor[0];
+ switch (c) {
+ case 'L':
+ case '[':
+ num_ref++;
+ break;
+ case 'J':
+ case 'D':
+ num_64++;
+ break;
+ case 'I':
+ case 'F':
+ num_32++;
+ break;
+ case 'S':
+ case 'C':
+ num_16++;
+ break;
+ case 'B':
+ case 'Z':
+ num_8++;
+ break;
+ default:
+ LOG(FATAL) << "Unknown descriptor: " << c;
+ UNREACHABLE();
+ }
}
}
return mirror::Class::ComputeClassSize(false,
@@ -2876,15 +2877,17 @@ void ClassLinker::FixupStaticTrampolines(ObjPtr<mirror::Class> klass) {
const DexFile& dex_file = klass->GetDexFile();
const DexFile::ClassDef* dex_class_def = klass->GetClassDef();
CHECK(dex_class_def != nullptr);
- ClassAccessor accessor(dex_file, *dex_class_def);
+ const uint8_t* class_data = dex_file.GetClassData(*dex_class_def);
// There should always be class data if there were direct methods.
- CHECK(accessor.HasClassData()) << klass->PrettyDescriptor();
+ CHECK(class_data != nullptr) << klass->PrettyDescriptor();
+ ClassDataItemIterator it(dex_file, class_data);
+ it.SkipAllFields();
bool has_oat_class;
OatFile::OatClass oat_class = OatFile::FindOatClass(dex_file,
klass->GetDexClassDefIndex(),
&has_oat_class);
// Link the code of methods skipped by LinkCode.
- for (size_t method_index = 0; method_index < accessor.NumDirectMethods(); ++method_index) {
+ for (size_t method_index = 0; it.HasNextDirectMethod(); ++method_index, it.Next()) {
ArtMethod* method = klass->GetDirectMethod(method_index, image_pointer_size_);
if (!method->IsStatic()) {
// Only update static methods.
@@ -2993,6 +2996,17 @@ void ClassLinker::SetupClass(const DexFile& dex_file,
klass->SetDexTypeIndex(dex_class_def.class_idx_);
}
+void ClassLinker::LoadClass(Thread* self,
+ const DexFile& dex_file,
+ const DexFile::ClassDef& dex_class_def,
+ Handle<mirror::Class> klass) {
+ const uint8_t* class_data = dex_file.GetClassData(dex_class_def);
+ if (class_data == nullptr) {
+ return; // no fields or methods - for example a marker interface
+ }
+ LoadClassMembers(self, dex_file, class_data, klass);
+}
+
LengthPrefixedArray<ArtField>* ClassLinker::AllocArtFieldArray(Thread* self,
LinearAlloc* allocator,
size_t length) {
@@ -3051,15 +3065,10 @@ LinearAlloc* ClassLinker::GetOrCreateAllocatorForClassLoader(ObjPtr<mirror::Clas
return allocator;
}
-void ClassLinker::LoadClass(Thread* self,
- const DexFile& dex_file,
- const DexFile::ClassDef& dex_class_def,
- Handle<mirror::Class> klass) {
- ClassAccessor accessor(dex_file, dex_class_def);
- if (!accessor.HasClassData()) {
- return;
- }
- Runtime* const runtime = Runtime::Current();
+void ClassLinker::LoadClassMembers(Thread* self,
+ const DexFile& dex_file,
+ const uint8_t* class_data,
+ Handle<mirror::Class> klass) {
{
// Note: We cannot have thread suspension until the field and method arrays are setup or else
// Class::VisitFieldRoots may miss some fields or methods.
@@ -3068,79 +3077,45 @@ void ClassLinker::LoadClass(Thread* self,
// We allow duplicate definitions of the same field in a class_data_item
// but ignore the repeated indexes here, b/21868015.
LinearAlloc* const allocator = GetAllocatorForClassLoader(klass->GetClassLoader());
+ ClassDataItemIterator it(dex_file, class_data);
LengthPrefixedArray<ArtField>* sfields = AllocArtFieldArray(self,
allocator,
- accessor.NumStaticFields());
+ it.NumStaticFields());
+ size_t num_sfields = 0;
+ uint32_t last_field_idx = 0u;
+ for (; it.HasNextStaticField(); it.Next()) {
+ uint32_t field_idx = it.GetMemberIndex();
+ DCHECK_GE(field_idx, last_field_idx); // Ordering enforced by DexFileVerifier.
+ if (num_sfields == 0 || LIKELY(field_idx > last_field_idx)) {
+ DCHECK_LT(num_sfields, it.NumStaticFields());
+ LoadField(it, klass, &sfields->At(num_sfields));
+ ++num_sfields;
+ last_field_idx = field_idx;
+ }
+ }
+
+ // Load instance fields.
LengthPrefixedArray<ArtField>* ifields = AllocArtFieldArray(self,
allocator,
- accessor.NumInstanceFields());
- size_t num_sfields = 0u;
+ it.NumInstanceFields());
size_t num_ifields = 0u;
- uint32_t last_static_field_idx = 0u;
- uint32_t last_instance_field_idx = 0u;
-
- // Methods
- bool has_oat_class = false;
- const OatFile::OatClass oat_class = (runtime->IsStarted() && !runtime->IsAotCompiler())
- ? OatFile::FindOatClass(dex_file, klass->GetDexClassDefIndex(), &has_oat_class)
- : OatFile::OatClass::Invalid();
- const OatFile::OatClass* oat_class_ptr = has_oat_class ? &oat_class : nullptr;
- klass->SetMethodsPtr(
- AllocArtMethodArray(self, allocator, accessor.NumMethods()),
- accessor.NumDirectMethods(),
- accessor.NumVirtualMethods());
- size_t class_def_method_index = 0;
- uint32_t last_dex_method_index = dex::kDexNoIndex;
- size_t last_class_def_method_index = 0;
+ last_field_idx = 0u;
+ for (; it.HasNextInstanceField(); it.Next()) {
+ uint32_t field_idx = it.GetMemberIndex();
+ DCHECK_GE(field_idx, last_field_idx); // Ordering enforced by DexFileVerifier.
+ if (num_ifields == 0 || LIKELY(field_idx > last_field_idx)) {
+ DCHECK_LT(num_ifields, it.NumInstanceFields());
+ LoadField(it, klass, &ifields->At(num_ifields));
+ ++num_ifields;
+ last_field_idx = field_idx;
+ }
+ }
- // Use the visitor since the ranged based loops are bit slower from seeking. Seeking to the
- // methods needs to decode all of the fields.
- accessor.VisitFieldsAndMethods([&](
- const ClassAccessor::Field& field) REQUIRES_SHARED(Locks::mutator_lock_) {
- uint32_t field_idx = field.GetIndex();
- DCHECK_GE(field_idx, last_static_field_idx); // Ordering enforced by DexFileVerifier.
- if (num_sfields == 0 || LIKELY(field_idx > last_static_field_idx)) {
- LoadField(field, klass, &sfields->At(num_sfields));
- ++num_sfields;
- last_static_field_idx = field_idx;
- }
- }, [&](const ClassAccessor::Field& field) REQUIRES_SHARED(Locks::mutator_lock_) {
- uint32_t field_idx = field.GetIndex();
- DCHECK_GE(field_idx, last_instance_field_idx); // Ordering enforced by DexFileVerifier.
- if (num_ifields == 0 || LIKELY(field_idx > last_instance_field_idx)) {
- LoadField(field, klass, &ifields->At(num_ifields));
- ++num_ifields;
- last_instance_field_idx = field_idx;
- }
- }, [&](const ClassAccessor::Method& method) REQUIRES_SHARED(Locks::mutator_lock_) {
- ArtMethod* art_method = klass->GetDirectMethodUnchecked(class_def_method_index,
- image_pointer_size_);
- LoadMethod(dex_file, method, klass, art_method);
- LinkCode(this, art_method, oat_class_ptr, class_def_method_index);
- uint32_t it_method_index = method.GetIndex();
- if (last_dex_method_index == it_method_index) {
- // duplicate case
- art_method->SetMethodIndex(last_class_def_method_index);
- } else {
- art_method->SetMethodIndex(class_def_method_index);
- last_dex_method_index = it_method_index;
- last_class_def_method_index = class_def_method_index;
- }
- ++class_def_method_index;
- }, [&](const ClassAccessor::Method& method) REQUIRES_SHARED(Locks::mutator_lock_) {
- ArtMethod* art_method = klass->GetVirtualMethodUnchecked(
- class_def_method_index - accessor.NumDirectMethods(),
- image_pointer_size_);
- LoadMethod(dex_file, method, klass, art_method);
- LinkCode(this, art_method, oat_class_ptr, class_def_method_index);
- ++class_def_method_index;
- });
-
- if (UNLIKELY(num_ifields + num_sfields != accessor.NumFields())) {
+ if (UNLIKELY(num_sfields != it.NumStaticFields()) ||
+ UNLIKELY(num_ifields != it.NumInstanceFields())) {
LOG(WARNING) << "Duplicate fields in class " << klass->PrettyDescriptor()
- << " (unique static fields: " << num_sfields << "/" << accessor.NumStaticFields()
- << ", unique instance fields: " << num_ifields << "/" << accessor.NumInstanceFields()
- << ")";
+ << " (unique static fields: " << num_sfields << "/" << it.NumStaticFields()
+ << ", unique instance fields: " << num_ifields << "/" << it.NumInstanceFields() << ")";
// NOTE: Not shrinking the over-allocated sfields/ifields, just setting size.
if (sfields != nullptr) {
sfields->SetSize(num_sfields);
@@ -3154,49 +3129,87 @@ void ClassLinker::LoadClass(Thread* self,
DCHECK_EQ(klass->NumStaticFields(), num_sfields);
klass->SetIFieldsPtr(ifields);
DCHECK_EQ(klass->NumInstanceFields(), num_ifields);
+ // Load methods.
+ bool has_oat_class = false;
+ const OatFile::OatClass oat_class =
+ (Runtime::Current()->IsStarted() && !Runtime::Current()->IsAotCompiler())
+ ? OatFile::FindOatClass(dex_file, klass->GetDexClassDefIndex(), &has_oat_class)
+ : OatFile::OatClass::Invalid();
+ const OatFile::OatClass* oat_class_ptr = has_oat_class ? &oat_class : nullptr;
+ klass->SetMethodsPtr(
+ AllocArtMethodArray(self, allocator, it.NumDirectMethods() + it.NumVirtualMethods()),
+ it.NumDirectMethods(),
+ it.NumVirtualMethods());
+ size_t class_def_method_index = 0;
+ uint32_t last_dex_method_index = dex::kDexNoIndex;
+ size_t last_class_def_method_index = 0;
+ // TODO These should really use the iterators.
+ for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) {
+ ArtMethod* method = klass->GetDirectMethodUnchecked(i, image_pointer_size_);
+ LoadMethod(dex_file, it, klass, method);
+ LinkCode(this, method, oat_class_ptr, class_def_method_index);
+ uint32_t it_method_index = it.GetMemberIndex();
+ if (last_dex_method_index == it_method_index) {
+ // duplicate case
+ method->SetMethodIndex(last_class_def_method_index);
+ } else {
+ method->SetMethodIndex(class_def_method_index);
+ last_dex_method_index = it_method_index;
+ last_class_def_method_index = class_def_method_index;
+ }
+ class_def_method_index++;
+ }
+ for (size_t i = 0; it.HasNextVirtualMethod(); i++, it.Next()) {
+ ArtMethod* method = klass->GetVirtualMethodUnchecked(i, image_pointer_size_);
+ LoadMethod(dex_file, it, klass, method);
+ DCHECK_EQ(class_def_method_index, it.NumDirectMethods() + i);
+ LinkCode(this, method, oat_class_ptr, class_def_method_index);
+ class_def_method_index++;
+ }
+ DCHECK(!it.HasNext());
}
// Ensure that the card is marked so that remembered sets pick up native roots.
Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(klass.Get());
self->AllowThreadSuspension();
}
-void ClassLinker::LoadField(const ClassAccessor::Field& field,
+void ClassLinker::LoadField(const ClassDataItemIterator& it,
Handle<mirror::Class> klass,
ArtField* dst) {
- const uint32_t field_idx = field.GetIndex();
+ const uint32_t field_idx = it.GetMemberIndex();
dst->SetDexFieldIndex(field_idx);
dst->SetDeclaringClass(klass.Get());
// Get access flags from the DexFile. If this is a boot class path class,
// also set its runtime hidden API access flags.
- uint32_t access_flags = field.GetAccessFlags();
+ uint32_t access_flags = it.GetFieldAccessFlags();
if (klass->IsBootStrapClassLoaded()) {
access_flags =
- HiddenApiAccessFlags::EncodeForRuntime(access_flags, field.DecodeHiddenAccessFlags());
+ HiddenApiAccessFlags::EncodeForRuntime(access_flags, it.DecodeHiddenAccessFlags());
}
dst->SetAccessFlags(access_flags);
}
void ClassLinker::LoadMethod(const DexFile& dex_file,
- const ClassAccessor::Method& method,
+ const ClassDataItemIterator& it,
Handle<mirror::Class> klass,
ArtMethod* dst) {
- const uint32_t dex_method_idx = method.GetIndex();
+ uint32_t dex_method_idx = it.GetMemberIndex();
const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx);
const char* method_name = dex_file.StringDataByIdx(method_id.name_idx_);
ScopedAssertNoThreadSuspension ants("LoadMethod");
dst->SetDexMethodIndex(dex_method_idx);
dst->SetDeclaringClass(klass.Get());
- dst->SetCodeItemOffset(method.GetCodeItemOffset());
+ dst->SetCodeItemOffset(it.GetMethodCodeItemOffset());
// Get access flags from the DexFile. If this is a boot class path class,
// also set its runtime hidden API access flags.
- uint32_t access_flags = method.GetAccessFlags();
+ uint32_t access_flags = it.GetMethodAccessFlags();
if (klass->IsBootStrapClassLoaded()) {
access_flags =
- HiddenApiAccessFlags::EncodeForRuntime(access_flags, method.DecodeHiddenAccessFlags());
+ HiddenApiAccessFlags::EncodeForRuntime(access_flags, it.DecodeHiddenAccessFlags());
}
if (UNLIKELY(strcmp("finalize", method_name) == 0)) {
@@ -4759,29 +4772,24 @@ bool ClassLinker::InitializeClass(Thread* self, Handle<mirror::Class> klass,
this,
*dex_class_def);
const DexFile& dex_file = *dex_cache->GetDexFile();
-
+ const uint8_t* class_data = dex_file.GetClassData(*dex_class_def);
+ ClassDataItemIterator field_it(dex_file, class_data);
if (value_it.HasNext()) {
- ClassAccessor accessor(dex_file, *dex_class_def);
+ DCHECK(field_it.HasNextStaticField());
CHECK(can_init_statics);
- for (const ClassAccessor::Field& field : accessor.GetStaticFields()) {
- if (!value_it.HasNext()) {
- break;
- }
- ArtField* art_field = ResolveField(field.GetIndex(),
- dex_cache,
- class_loader,
- /* is_static */ true);
+ for ( ; value_it.HasNext(); value_it.Next(), field_it.Next()) {
+ ArtField* field = ResolveField(
+ field_it.GetMemberIndex(), dex_cache, class_loader, /* is_static */ true);
if (Runtime::Current()->IsActiveTransaction()) {
- value_it.ReadValueToField<true>(art_field);
+ value_it.ReadValueToField<true>(field);
} else {
- value_it.ReadValueToField<false>(art_field);
+ value_it.ReadValueToField<false>(field);
}
if (self->IsExceptionPending()) {
break;
}
- value_it.Next();
+ DCHECK(!value_it.HasNext() || field_it.HasNextStaticField());
}
- DCHECK(self->IsExceptionPending() || !value_it.HasNext());
}
}