diff options
| -rw-r--r-- | dex2oat/linker/image_writer.cc | 5 | ||||
| -rw-r--r-- | runtime/class_linker.cc | 10 | ||||
| -rw-r--r-- | runtime/mirror/class.cc | 140 |
3 files changed, 76 insertions, 79 deletions
diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc index b69c750fd2..34ec5a8a6f 100644 --- a/dex2oat/linker/image_writer.cc +++ b/dex2oat/linker/image_writer.cc @@ -2131,8 +2131,9 @@ void ImageWriter::LayoutHelper::VerifyImageBinSlotsAssigned() { // Ignore finalizer references for the dalvik.system.DexFile objects referenced by // the app class loader. if (obj->IsFinalizerReferenceInstance()) { - ArtField* ref_field = - obj->GetClass()->FindInstanceField("referent", "Ljava/lang/Object;"); + DCHECK(obj->GetClass()->GetSuperClass()->DescriptorEquals("Ljava/lang/ref/Reference;")); + ArtField* ref_field = obj->GetClass()->GetSuperClass()->FindDeclaredInstanceField( + "referent", "Ljava/lang/Object;"); CHECK(ref_field != nullptr); ObjPtr<mirror::Object> ref = ref_field->GetObject(obj); CHECK(ref != nullptr); diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index f0c9507ca0..c2cbe791ce 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -9320,16 +9320,6 @@ ArtField* ClassLinker::FindResolvedField(ObjPtr<mirror::Class> klass, bool is_static) { ArtField* resolved = is_static ? klass->FindStaticField(dex_cache, field_idx) : klass->FindInstanceField(dex_cache, field_idx); - - if (resolved == nullptr) { - const DexFile& dex_file = *dex_cache->GetDexFile(); - const dex::FieldId& field_id = dex_file.GetFieldId(field_idx); - const char* name = dex_file.GetFieldName(field_id); - const char* type = dex_file.GetFieldTypeDescriptor(field_id); - resolved = is_static ? klass->FindStaticField(name, type) - : klass->FindInstanceField(name, type); - } - if (resolved != nullptr && hiddenapi::ShouldDenyAccessToMember(resolved, hiddenapi::AccessContext(class_loader, dex_cache), diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index 110a8c541b..7c7005004a 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -974,18 +974,6 @@ ArtField* Class::FindInstanceField(std::string_view name, std::string_view type) return nullptr; } -ArtField* Class::FindInstanceField(ObjPtr<DexCache> dex_cache, uint32_t dex_field_idx) { - // Is the field in this class, or any of its superclasses? - // Interfaces are not relevant because they can't contain instance fields. - for (ObjPtr<Class> c = this; c != nullptr; c = c->GetSuperClass()) { - ArtField* f = c->FindDeclaredInstanceField(dex_cache, dex_field_idx); - if (f != nullptr) { - return f; - } - } - return nullptr; -} - ArtField* Class::FindDeclaredStaticField(std::string_view name, std::string_view type) { DCHECK(!type.empty()); LengthPrefixedArray<ArtField>* sfields = GetSFieldsPtr(); @@ -1046,43 +1034,34 @@ ArtField* Class::FindStaticField(std::string_view name, std::string_view type) { return nullptr; } -ArtField* Class::FindStaticField(ObjPtr<DexCache> dex_cache, uint32_t dex_field_idx) { - ScopedAssertNoThreadSuspension ants(__FUNCTION__); - for (ObjPtr<Class> k = this; k != nullptr; k = k->GetSuperClass()) { - // Is the field in this class? - ArtField* f = k->FindDeclaredStaticField(dex_cache, dex_field_idx); - if (f != nullptr) { - return f; - } - // Is this field in any of this class' interfaces? - for (uint32_t i = 0, num_interfaces = k->NumDirectInterfaces(); i != num_interfaces; ++i) { - ObjPtr<Class> interface = k->GetDirectInterface(i); - DCHECK(interface != nullptr); - f = interface->FindStaticField(dex_cache, dex_field_idx); - if (f != nullptr) { - return f; - } - } - } - return nullptr; -} +// Find a field using the JLS field resolution order. +// Template arguments can be used to limit the search to either static or instance fields. +// The search should be limited only if we know that a full search would yield a field of +// the right type or no field at all. This can be known for field references in a method +// if we have previously verified that method and did not find a field type mismatch. +template <bool kSearchInstanceFields, bool kSearchStaticFields> +ALWAYS_INLINE +ArtField* FindFieldImpl(ObjPtr<mirror::Class> klass, + ObjPtr<mirror::DexCache> dex_cache, + uint32_t field_idx) REQUIRES_SHARED(Locks::mutator_lock_) { + static_assert(kSearchInstanceFields || kSearchStaticFields); -// Find a field using the JLS field resolution order -FLATTEN -ArtField* Class::FindField(ObjPtr<mirror::DexCache> dex_cache, uint32_t field_idx) { // FIXME: Hijacking a proxy class by a custom class loader can break this assumption. - DCHECK(!IsProxyClass()); + DCHECK(!klass->IsProxyClass()); ScopedAssertNoThreadSuspension ants(__FUNCTION__); // First try to find a declared field by `field_idx` if we have a `dex_cache` match. - ObjPtr<DexCache> this_dex_cache = GetDexCache(); - if (this_dex_cache == dex_cache) { + ObjPtr<DexCache> klass_dex_cache = klass->GetDexCache(); + if (klass_dex_cache == dex_cache) { // Lookup is always performed in the class referenced by the FieldId. - DCHECK_EQ(dex_type_idx_, this_dex_cache->GetDexFile()->GetFieldId(field_idx).class_idx_.index_); - ArtField* f = FindDeclaredInstanceField(this_dex_cache, field_idx); - if (f == nullptr) { - f = FindDeclaredStaticField(this_dex_cache, field_idx); + DCHECK_EQ(klass->GetDexTypeIndex(), + klass_dex_cache->GetDexFile()->GetFieldId(field_idx).class_idx_); + ArtField* f = kSearchInstanceFields + ? klass->FindDeclaredInstanceField(klass_dex_cache, field_idx) + : nullptr; + if (kSearchStaticFields && f == nullptr) { + f = klass->FindDeclaredStaticField(klass_dex_cache, field_idx); } if (f != nullptr) { return f; @@ -1127,65 +1106,92 @@ ArtField* Class::FindField(ObjPtr<mirror::DexCache> dex_cache, uint32_t field_id }; // If we had a dex cache mismatch, search declared fields by name and type. - if (this_dex_cache != dex_cache && (GetIFieldsPtr() != nullptr || GetSFieldsPtr() != nullptr)) { + if (klass_dex_cache != dex_cache && + ((kSearchInstanceFields && klass->GetIFieldsPtr() != nullptr) || + (kSearchStaticFields && klass->GetSFieldsPtr() != nullptr))) { ensure_name_and_type_initialized(); - ArtField* f = FindDeclaredInstanceField(name, type); - if (f == nullptr) { - f = FindDeclaredStaticField(name, type); + ArtField* f = kSearchInstanceFields ? klass->FindDeclaredInstanceField(name, type) : nullptr; + if (kSearchStaticFields && f == nullptr) { + f = klass->FindDeclaredStaticField(name, type); } if (f != nullptr) { return f; } } - // Search direct interfaces. - { - ArtField* f = search_direct_interfaces(this); + // Search direct interfaces for static fields. + if (kSearchStaticFields) { + ArtField* f = search_direct_interfaces(klass); if (f != nullptr) { return f; } } // Continue searching in superclasses. - for (ObjPtr<Class> k = GetSuperClass(); k != nullptr; k = k->GetSuperClass()) { + for (ObjPtr<Class> k = klass->GetSuperClass(); k != nullptr; k = k->GetSuperClass()) { // Is the field in this class? ObjPtr<DexCache> k_dex_cache = k->GetDexCache(); if (k_dex_cache == dex_cache) { // Matching dex_cache. We cannot compare the `field_idx` anymore because // the type index differs, so compare the name index and type index. - for (ArtField& field : k->GetIFields()) { - const dex::FieldId& other_field_id = dex_file.GetFieldId(field.GetDexFieldIndex()); - if (other_field_id.name_idx_ == field_id.name_idx_ && - other_field_id.type_idx_ == field_id.type_idx_) { - return &field; + if (kSearchInstanceFields) { + for (ArtField& field : k->GetIFields()) { + const dex::FieldId& other_field_id = dex_file.GetFieldId(field.GetDexFieldIndex()); + if (other_field_id.name_idx_ == field_id.name_idx_ && + other_field_id.type_idx_ == field_id.type_idx_) { + return &field; + } } } - for (ArtField& field : k->GetSFields()) { - const dex::FieldId& other_field_id = dex_file.GetFieldId(field.GetDexFieldIndex()); - if (other_field_id.name_idx_ == field_id.name_idx_ && - other_field_id.type_idx_ == field_id.type_idx_) { - return &field; + if (kSearchStaticFields) { + for (ArtField& field : k->GetSFields()) { + const dex::FieldId& other_field_id = dex_file.GetFieldId(field.GetDexFieldIndex()); + if (other_field_id.name_idx_ == field_id.name_idx_ && + other_field_id.type_idx_ == field_id.type_idx_) { + return &field; + } } } - } else if (k->GetIFieldsPtr() != nullptr || k->GetSFieldsPtr() != nullptr) { + } else if ((kSearchInstanceFields && k->GetIFieldsPtr() != nullptr) || + (kSearchStaticFields && k->GetSFieldsPtr() != nullptr)) { ensure_name_and_type_initialized(); - ArtField* f = k->FindDeclaredInstanceField(name, type); - if (f == nullptr) { + ArtField* f = kSearchInstanceFields ? k->FindDeclaredInstanceField(name, type) : nullptr; + if (kSearchStaticFields && f == nullptr) { f = k->FindDeclaredStaticField(name, type); } if (f != nullptr) { return f; } } - // Is this field in any of this class' interfaces? - ArtField* f = search_direct_interfaces(k); - if (f != nullptr) { - return f; + if (kSearchStaticFields) { + // Is this field in any of this class' interfaces? + ArtField* f = search_direct_interfaces(k); + if (f != nullptr) { + return f; + } } } return nullptr; } +FLATTEN +ArtField* Class::FindField(ObjPtr<mirror::DexCache> dex_cache, uint32_t field_idx) { + return FindFieldImpl</*kSearchInstanceFields=*/ true, + /*kSearchStaticFields*/ true>(this, dex_cache, field_idx); +} + +FLATTEN +ArtField* Class::FindInstanceField(ObjPtr<mirror::DexCache> dex_cache, uint32_t field_idx) { + return FindFieldImpl</*kSearchInstanceFields=*/ true, + /*kSearchStaticFields*/ false>(this, dex_cache, field_idx); +} + +FLATTEN +ArtField* Class::FindStaticField(ObjPtr<mirror::DexCache> dex_cache, uint32_t field_idx) { + return FindFieldImpl</*kSearchInstanceFields=*/ false, + /*kSearchStaticFields*/ true>(this, dex_cache, field_idx); +} + void Class::ClearSkipAccessChecksFlagOnAllMethods(PointerSize pointer_size) { DCHECK(IsVerified()); for (auto& m : GetMethods(pointer_size)) { |