diff options
Diffstat (limited to 'runtime/mirror/class.cc')
-rw-r--r-- | runtime/mirror/class.cc | 211 |
1 files changed, 82 insertions, 129 deletions
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index a122393171..327d2b78f1 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -426,22 +426,15 @@ void Class::DumpClass(std::ostream& os, int flags) { os << StringPrintf(" %2zd: %s\n", i, ArtMethod::PrettyMethod( GetDirectMethod(i, image_pointer_size)).c_str()); } - if (NumStaticFields() > 0) { - os << " static fields (" << NumStaticFields() << " entries):\n"; + if (NumFields() > 0) { + os << " fields (" << NumFields() << " entries):\n"; if (IsResolved()) { - for (size_t i = 0; i < NumStaticFields(); ++i) { - os << StringPrintf(" %2zd: %s\n", i, ArtField::PrettyField(GetStaticField(i)).c_str()); - } - } else { - os << " <not yet available>"; - } - } - if (NumInstanceFields() > 0) { - os << " instance fields (" << NumInstanceFields() << " entries):\n"; - if (IsResolved()) { - for (size_t i = 0; i < NumInstanceFields(); ++i) { - os << StringPrintf(" %2zd: %s\n", i, - ArtField::PrettyField(GetInstanceField(i)).c_str()); + for (size_t i = 0; i < NumFields(); ++i) { + ArtField* field = GetField(i); + os << StringPrintf(" %2zd: %s %s\n", + i, + field->IsStatic() ? "static" : "instance", + ArtField::PrettyField(field).c_str()); } } else { os << " <not yet available>"; @@ -1107,25 +1100,30 @@ static std::tuple<bool, ArtField*> FindFieldByNameAndType(const DexFile& dex_fil return {false, nullptr}; } -ArtField* Class::FindDeclaredInstanceField(std::string_view name, std::string_view type) { +ArtField* Class::FindDeclaredField(std::string_view name, std::string_view type) { // Binary search by name. Interfaces are not relevant because they can't contain instance fields. - LengthPrefixedArray<ArtField>* ifields = GetIFieldsPtr(); - if (ifields == nullptr) { + LengthPrefixedArray<ArtField>* fields = GetFieldsPtr(); + if (fields == nullptr) { return nullptr; } DCHECK(!IsProxyClass()); - auto [success, field] = FindFieldByNameAndType(GetDexFile(), ifields, name, type); + auto [success, field] = FindFieldByNameAndType(GetDexFile(), fields, name, type); DCHECK_EQ(success, field != nullptr); return field; } +ArtField* Class::FindDeclaredInstanceField(std::string_view name, std::string_view type) { + ArtField* f = FindDeclaredField(name, type); + if (f != nullptr && !f->IsStatic()) { + return f; + } + return nullptr; +} + ArtField* Class::FindDeclaredInstanceField(ObjPtr<DexCache> dex_cache, uint32_t dex_field_idx) { - if (GetDexCache() == dex_cache) { - for (ArtField& field : GetIFields()) { - if (field.GetDexFieldIndex() == dex_field_idx) { - return &field; - } - } + ArtField* f = FindDeclaredField(dex_cache, dex_field_idx); + if (f != nullptr && !f->IsStatic()) { + return f; } return nullptr; } @@ -1144,35 +1142,39 @@ ArtField* Class::FindInstanceField(std::string_view name, std::string_view type) ArtField* Class::FindDeclaredStaticField(std::string_view name, std::string_view type) { DCHECK(!type.empty()); - LengthPrefixedArray<ArtField>* sfields = GetSFieldsPtr(); - if (sfields == nullptr) { + LengthPrefixedArray<ArtField>* fields = GetFieldsPtr(); + if (fields == nullptr) { return nullptr; } if (UNLIKELY(IsProxyClass())) { // Proxy fields do not have appropriate dex field indexes required by // `FindFieldByNameAndType()`. However, each proxy class has exactly // the same artificial fields created by the `ClassLinker`. - DCHECK_EQ(sfields->size(), 2u); - DCHECK_EQ(strcmp(sfields->At(0).GetName(), "interfaces"), 0); - DCHECK_EQ(strcmp(sfields->At(0).GetTypeDescriptor(), "[Ljava/lang/Class;"), 0); - DCHECK_EQ(strcmp(sfields->At(1).GetName(), "throws"), 0); - DCHECK_EQ(strcmp(sfields->At(1).GetTypeDescriptor(), "[[Ljava/lang/Class;"), 0); + DCHECK_EQ(fields->size(), 2u); + DCHECK_EQ(strcmp(fields->At(0).GetName(), "interfaces"), 0); + DCHECK_EQ(strcmp(fields->At(0).GetTypeDescriptor(), "[Ljava/lang/Class;"), 0); + DCHECK(fields->At(0).IsStatic()); + DCHECK_EQ(strcmp(fields->At(1).GetName(), "throws"), 0); + DCHECK_EQ(strcmp(fields->At(1).GetTypeDescriptor(), "[[Ljava/lang/Class;"), 0); + DCHECK(fields->At(1).IsStatic()); if (name == "interfaces") { - return (type == "[Ljava/lang/Class;") ? &sfields->At(0) : nullptr; + return (type == "[Ljava/lang/Class;") ? &fields->At(0) : nullptr; } else if (name == "throws") { - return (type == "[[Ljava/lang/Class;") ? &sfields->At(1) : nullptr; + return (type == "[[Ljava/lang/Class;") ? &fields->At(1) : nullptr; } else { return nullptr; } } - auto [success, field] = FindFieldByNameAndType(GetDexFile(), sfields, name, type); - DCHECK_EQ(success, field != nullptr); - return field; + ArtField* f = FindDeclaredField(name, type); + if (f != nullptr && f->IsStatic()) { + return f; + } + return nullptr; } -ArtField* Class::FindDeclaredStaticField(ObjPtr<DexCache> dex_cache, uint32_t dex_field_idx) { +ArtField* Class::FindDeclaredField(ObjPtr<DexCache> dex_cache, uint32_t dex_field_idx) { if (dex_cache == GetDexCache()) { - for (ArtField& field : GetSFields()) { + for (ArtField& field : GetFields()) { if (field.GetDexFieldIndex() == dex_field_idx) { return &field; } @@ -1181,6 +1183,14 @@ ArtField* Class::FindDeclaredStaticField(ObjPtr<DexCache> dex_cache, uint32_t de return nullptr; } +ArtField* Class::FindDeclaredStaticField(ObjPtr<DexCache> dex_cache, uint32_t dex_field_idx) { + ArtField* f = FindDeclaredField(dex_cache, dex_field_idx); + if (f != nullptr && f->IsStatic()) { + return f; + } + return nullptr; +} + ObjPtr<mirror::ObjectArray<mirror::Field>> Class::GetDeclaredFields( Thread* self, bool public_only, @@ -1190,17 +1200,11 @@ ObjPtr<mirror::ObjectArray<mirror::Field>> Class::GetDeclaredFields( return nullptr; } StackHandleScope<1> hs(self); - IterationRange<StrideIterator<ArtField>> ifields = GetIFields(); - IterationRange<StrideIterator<ArtField>> sfields = GetSFields(); - size_t array_size = NumInstanceFields() + NumStaticFields(); + IterationRange<StrideIterator<ArtField>> fields = GetFields(); + size_t array_size = NumFields(); auto hiddenapi_context = hiddenapi::GetReflectionCallerAccessContext(self); // Lets go subtract all the non discoverable fields. - for (ArtField& field : ifields) { - if (!IsDiscoverable(public_only, hiddenapi_context, &field)) { - --array_size; - } - } - for (ArtField& field : sfields) { + for (ArtField& field : fields) { if (!IsDiscoverable(public_only, hiddenapi_context, &field)) { --array_size; } @@ -1211,7 +1215,7 @@ ObjPtr<mirror::ObjectArray<mirror::Field>> Class::GetDeclaredFields( if (object_array == nullptr) { return nullptr; } - for (ArtField& field : ifields) { + for (ArtField& field : fields) { if (IsDiscoverable(public_only, hiddenapi_context, &field)) { ObjPtr<mirror::Field> reflect_field = mirror::Field::CreateFromArtField(self, &field, force_resolve); @@ -1229,23 +1233,6 @@ ObjPtr<mirror::ObjectArray<mirror::Field>> Class::GetDeclaredFields( array_idx++, reflect_field); } } - for (ArtField& field : sfields) { - if (IsDiscoverable(public_only, hiddenapi_context, &field)) { - ObjPtr<mirror::Field> reflect_field = - mirror::Field::CreateFromArtField(self, &field, force_resolve); - if (reflect_field == nullptr) { - if (kIsDebugBuild) { - self->AssertPendingException(); - } - return nullptr; - } - // We're initializing a newly allocated object, so we do not need to record that under - // a transaction. If the transaction is aborted, the whole object shall be unreachable. - object_array->SetWithoutChecks</*kTransactionActive=*/ false, - /*kCheckTransaction=*/ false>( - array_idx++, reflect_field); - } - } DCHECK_EQ(array_idx, array_size); return object_array.Get(); } @@ -1274,17 +1261,15 @@ ArtField* Class::FindStaticField(std::string_view name, std::string_view type) { } // Find a field using the JLS field resolution order. -// Template arguments can be used to limit the search to either static or instance fields. +// Template arguments can be used to extend the search to static fields of interfaces. // 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> +template <bool kSearchStaticFieldsInInterfaces> 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); - // FIXME: Hijacking a proxy class by a custom class loader can break this assumption. DCHECK(!klass->IsProxyClass()); @@ -1296,12 +1281,7 @@ ArtField* FindFieldImpl(ObjPtr<mirror::Class> klass, // Lookup is always performed in the class referenced by the FieldId. 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); - } + ArtField* f = klass->FindDeclaredField(klass_dex_cache, field_idx); if (f != nullptr) { return f; } @@ -1346,27 +1326,14 @@ ArtField* FindFieldImpl(ObjPtr<mirror::Class> klass, auto find_field_by_name_and_type = [&](ObjPtr<mirror::Class> k, ObjPtr<DexCache> k_dex_cache) REQUIRES_SHARED(Locks::mutator_lock_) -> std::tuple<bool, ArtField*> { - if ((!kSearchInstanceFields || k->GetIFieldsPtr() == nullptr) && - (!kSearchStaticFields || k->GetSFieldsPtr() == nullptr)) { + if (k->GetFieldsPtr() == nullptr) { return {false, nullptr}; } ensure_name_and_type_initialized(); const DexFile& k_dex_file = *k_dex_cache->GetDexFile(); - if (kSearchInstanceFields && k->GetIFieldsPtr() != nullptr) { - auto [success, field] = FindFieldByNameAndType(k_dex_file, k->GetIFieldsPtr(), name, type); - DCHECK_EQ(success, field != nullptr); - if (success) { - return {true, field}; - } - } - if (kSearchStaticFields && k->GetSFieldsPtr() != nullptr) { - auto [success, field] = FindFieldByNameAndType(k_dex_file, k->GetSFieldsPtr(), name, type); - DCHECK_EQ(success, field != nullptr); - if (success) { - return {true, field}; - } - } - return {false, nullptr}; + auto [success, field] = FindFieldByNameAndType(k_dex_file, k->GetFieldsPtr(), name, type); + DCHECK_EQ(success, field != nullptr); + return {success, field}; }; // If we had a dex cache mismatch, search declared fields by name and type. @@ -1379,7 +1346,7 @@ ArtField* FindFieldImpl(ObjPtr<mirror::Class> klass, } // Search direct interfaces for static fields. - if (kSearchStaticFields) { + if (kSearchStaticFieldsInInterfaces) { ArtField* f = search_direct_interfaces(klass); if (f != nullptr) { return f; @@ -1393,22 +1360,11 @@ ArtField* FindFieldImpl(ObjPtr<mirror::Class> klass, 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. - 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; - } - } - } - 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; - } + for (ArtField& field : k->GetFields()) { + 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 { @@ -1418,7 +1374,7 @@ ArtField* FindFieldImpl(ObjPtr<mirror::Class> klass, return field; } } - if (kSearchStaticFields) { + if (kSearchStaticFieldsInInterfaces) { // Is this field in any of this class' interfaces? ArtField* f = search_direct_interfaces(k); if (f != nullptr) { @@ -1431,20 +1387,17 @@ ArtField* FindFieldImpl(ObjPtr<mirror::Class> klass, FLATTEN ArtField* Class::FindField(ObjPtr<mirror::DexCache> dex_cache, uint32_t field_idx) { - return FindFieldImpl</*kSearchInstanceFields=*/ true, - /*kSearchStaticFields*/ true>(this, dex_cache, field_idx); + return FindFieldImpl</*kSearchStaticFieldsInInterfaces*/ 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); + return FindFieldImpl</*kSearchStaticFieldsInInterfaces*/ 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); + return FindFieldImpl</*kSearchStaticFieldsInInterfaces*/ true>(this, dex_cache, field_idx); } void Class::ClearSkipAccessChecksFlagOnAllMethods(PointerSize pointer_size) { @@ -2247,7 +2200,7 @@ bool Class::EnsureStaticFieldIds(Handle<Class> h_this) { self->AssertPendingOOMException(); return false; } - return ext->EnsureStaticJFieldIDsArrayPresent(h_this->NumStaticFields()); + return ext->EnsureStaticJFieldIDsArrayPresent(h_this->NumFields()); } ObjPtr<Object> Class::GetInstanceFieldIds() { ObjPtr<ClassExt> ext(GetExtData()); @@ -2265,42 +2218,42 @@ bool Class::EnsureInstanceFieldIds(Handle<Class> h_this) { self->AssertPendingOOMException(); return false; } - return ext->EnsureInstanceJFieldIDsArrayPresent(h_this->NumInstanceFields()); + return ext->EnsureInstanceJFieldIDsArrayPresent(h_this->NumFields()); } size_t Class::GetStaticFieldIdOffset(ArtField* field) { DCHECK_LT(reinterpret_cast<uintptr_t>(field), - reinterpret_cast<uintptr_t>(&*GetSFieldsPtr()->end())) + reinterpret_cast<uintptr_t>(&*GetFieldsPtr()->end())) << "field not part of the current class. " << field->PrettyField() << " class is " << PrettyClass(); DCHECK_GE(reinterpret_cast<uintptr_t>(field), - reinterpret_cast<uintptr_t>(&*GetSFieldsPtr()->begin())) + reinterpret_cast<uintptr_t>(&*GetFieldsPtr()->begin())) << "field not part of the current class. " << field->PrettyField() << " class is " << PrettyClass(); - uintptr_t start = reinterpret_cast<uintptr_t>(&GetSFieldsPtr()->At(0)); + uintptr_t start = reinterpret_cast<uintptr_t>(&GetFieldsPtr()->At(0)); uintptr_t fld = reinterpret_cast<uintptr_t>(field); size_t res = (fld - start) / sizeof(ArtField); - DCHECK_EQ(&GetSFieldsPtr()->At(res), field) + DCHECK_EQ(&GetFieldsPtr()->At(res), field) << "Incorrect field computation expected: " << field->PrettyField() - << " got: " << GetSFieldsPtr()->At(res).PrettyField(); + << " got: " << GetFieldsPtr()->At(res).PrettyField(); return res; } size_t Class::GetInstanceFieldIdOffset(ArtField* field) { DCHECK_LT(reinterpret_cast<uintptr_t>(field), - reinterpret_cast<uintptr_t>(&*GetIFieldsPtr()->end())) + reinterpret_cast<uintptr_t>(&*GetFieldsPtr()->end())) << "field not part of the current class. " << field->PrettyField() << " class is " << PrettyClass(); DCHECK_GE(reinterpret_cast<uintptr_t>(field), - reinterpret_cast<uintptr_t>(&*GetIFieldsPtr()->begin())) + reinterpret_cast<uintptr_t>(&*GetFieldsPtr()->begin())) << "field not part of the current class. " << field->PrettyField() << " class is " << PrettyClass(); - uintptr_t start = reinterpret_cast<uintptr_t>(&GetIFieldsPtr()->At(0)); + uintptr_t start = reinterpret_cast<uintptr_t>(&GetFieldsPtr()->At(0)); uintptr_t fld = reinterpret_cast<uintptr_t>(field); size_t res = (fld - start) / sizeof(ArtField); - DCHECK_EQ(&GetIFieldsPtr()->At(res), field) + DCHECK_EQ(&GetFieldsPtr()->At(res), field) << "Incorrect field computation expected: " << field->PrettyField() - << " got: " << GetIFieldsPtr()->At(res).PrettyField(); + << " got: " << GetFieldsPtr()->At(res).PrettyField(); return res; } |