diff options
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r-- | runtime/class_linker.cc | 290 |
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()); } } |