summaryrefslogtreecommitdiff
path: root/runtime/class_linker.cc
diff options
context:
space:
mode:
author Nicolas Geoffray <ngeoffray@google.com> 2024-11-28 16:28:04 +0000
committer Nicolas Geoffray <ngeoffray@google.com> 2025-01-16 11:36:58 +0000
commit990cf07523a5c6ae437a0bd0cc80fb63320def5e (patch)
tree7d7160e014b14368c6cd8dcfcbfe9e2996f19e51 /runtime/class_linker.cc
parentae13bd8a14183069642a5eed4793cf34f5a2eadc (diff)
Merge sFields and iFields.
Test: test.py Change-Id: Ib97fca637a8866a41a4389b150c6000d9fb6d99b
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r--runtime/class_linker.cc140
1 files changed, 71 insertions, 69 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 1488cc6450..31d3acbbcd 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1102,23 +1102,29 @@ void ClassLinker::FinishInit(Thread* self) {
Handle<mirror::Class> java_lang_ref_FinalizerReference =
hs.NewHandle(FindSystemClass(self, "Ljava/lang/ref/FinalizerReference;"));
- ArtField* pendingNext = java_lang_ref_Reference->GetInstanceField(0);
+ ArtField* pendingNext = java_lang_ref_Reference->GetField(1);
+ CHECK(!pendingNext->IsStatic());
CHECK_STREQ(pendingNext->GetName(), "pendingNext");
CHECK_STREQ(pendingNext->GetTypeDescriptor(), "Ljava/lang/ref/Reference;");
- ArtField* queue = java_lang_ref_Reference->GetInstanceField(1);
+ ArtField* queue = java_lang_ref_Reference->GetField(2);
+ CHECK(!queue->IsStatic());
CHECK_STREQ(queue->GetName(), "queue");
CHECK_STREQ(queue->GetTypeDescriptor(), "Ljava/lang/ref/ReferenceQueue;");
- ArtField* queueNext = java_lang_ref_Reference->GetInstanceField(2);
+ ArtField* queueNext = java_lang_ref_Reference->GetField(3);
+ CHECK(!queueNext->IsStatic());
CHECK_STREQ(queueNext->GetName(), "queueNext");
CHECK_STREQ(queueNext->GetTypeDescriptor(), "Ljava/lang/ref/Reference;");
- ArtField* referent = java_lang_ref_Reference->GetInstanceField(3);
+ ArtField* referent = java_lang_ref_Reference->GetField(4);
+ CHECK(!referent->IsStatic());
CHECK_STREQ(referent->GetName(), "referent");
CHECK_STREQ(referent->GetTypeDescriptor(), "Ljava/lang/Object;");
- ArtField* zombie = java_lang_ref_FinalizerReference->GetInstanceField(2);
+ ArtField* zombie = java_lang_ref_FinalizerReference->GetField(
+ java_lang_ref_FinalizerReference->NumFields() - 1);
+ CHECK(!zombie->IsStatic());
CHECK_STREQ(zombie->GetName(), "zombie");
CHECK_STREQ(zombie->GetTypeDescriptor(), "Ljava/lang/Object;");
@@ -2003,10 +2009,7 @@ class ImageChecker final {
CHECK(class_class != nullptr) << "Null class class " << obj;
if (obj_klass == class_class) {
auto klass = obj->AsClass();
- for (ArtField& field : klass->GetIFields()) {
- CHECK_EQ(field.GetDeclaringClass<kWithoutReadBarrier>(), klass);
- }
- for (ArtField& field : klass->GetSFields()) {
+ for (ArtField& field : klass->GetFields()) {
CHECK_EQ(field.GetDeclaringClass<kWithoutReadBarrier>(), klass);
}
for (ArtMethod& m : klass->GetMethods(kPointerSize)) {
@@ -4019,12 +4022,11 @@ 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());
- LengthPrefixedArray<ArtField>* sfields = AllocArtFieldArray(self,
- allocator,
- accessor.NumStaticFields());
- LengthPrefixedArray<ArtField>* ifields = AllocArtFieldArray(self,
- allocator,
- accessor.NumInstanceFields());
+ LengthPrefixedArray<ArtField>* fields =
+ AllocArtFieldArray(self,
+ allocator,
+ accessor.NumStaticFields() + accessor.NumInstanceFields());
+ size_t num_fields = 0u;
size_t num_sfields = 0u;
size_t num_ifields = 0u;
uint32_t last_static_field_idx = 0u;
@@ -4056,7 +4058,8 @@ void ClassLinker::LoadClass(Thread* self,
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));
+ LoadField(field, klass, &fields->At(num_fields));
+ ++num_fields;
++num_sfields;
last_static_field_idx = field_idx;
}
@@ -4064,7 +4067,8 @@ void ClassLinker::LoadClass(Thread* self,
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));
+ LoadField(field, klass, &fields->At(num_fields));
+ ++num_fields;
++num_ifields;
last_instance_field_idx = field_idx;
}
@@ -4094,24 +4098,27 @@ void ClassLinker::LoadClass(Thread* self,
++class_def_method_index;
});
- if (UNLIKELY(num_ifields + num_sfields != accessor.NumFields())) {
+ if (UNLIKELY(num_fields != accessor.NumFields())) {
LOG(WARNING) << "Duplicate fields in class " << klass->PrettyDescriptor()
<< " (unique static fields: " << num_sfields << "/" << accessor.NumStaticFields()
<< ", unique instance fields: " << num_ifields << "/" << accessor.NumInstanceFields()
<< ")";
- // NOTE: Not shrinking the over-allocated sfields/ifields, just setting size.
- if (sfields != nullptr) {
- sfields->SetSize(num_sfields);
- }
- if (ifields != nullptr) {
- ifields->SetSize(num_ifields);
+ // NOTE: Not shrinking the over-allocated fields, just setting size.
+ if (fields != nullptr) {
+ fields->SetSize(num_fields);
}
}
- // Set the field arrays.
- klass->SetSFieldsPtr(sfields);
- DCHECK_EQ(klass->NumStaticFields(), num_sfields);
- klass->SetIFieldsPtr(ifields);
- DCHECK_EQ(klass->NumInstanceFields(), num_ifields);
+ if (fields != nullptr) {
+ // Sort the fields by dex field index to facilitate fast lookups.
+ std::sort(fields->begin(),
+ fields->end(),
+ [](ArtField& lhs, ArtField& rhs) {
+ return lhs.GetDexFieldIndex() < rhs.GetDexFieldIndex();
+ });
+ }
+
+ // Set the field array.
+ klass->SetFieldsPtr(fields);
}
// Ensure that the card is marked so that remembered sets pick up native roots.
WriteBarrier::ForEveryFieldWrite(klass.Get());
@@ -5304,18 +5311,18 @@ ObjPtr<mirror::Class> ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRun
// Instance fields are inherited, but we add a couple of static fields...
const size_t num_fields = 2;
- LengthPrefixedArray<ArtField>* sfields = AllocArtFieldArray(self, allocator, num_fields);
- temp_klass->SetSFieldsPtr(sfields);
+ LengthPrefixedArray<ArtField>* fields = AllocArtFieldArray(self, allocator, num_fields);
+ temp_klass->SetFieldsPtr(fields);
// 1. Create a static field 'interfaces' that holds the _declared_ interfaces implemented by
// our proxy, so Class.getInterfaces doesn't return the flattened set.
- ArtField& interfaces_sfield = sfields->At(0);
+ ArtField& interfaces_sfield = fields->At(0);
interfaces_sfield.SetDexFieldIndex(0);
interfaces_sfield.SetDeclaringClass(temp_klass.Get());
interfaces_sfield.SetAccessFlags(kAccStatic | kAccPublic | kAccFinal);
// 2. Create a static field 'throws' that holds exceptions thrown by our methods.
- ArtField& throws_sfield = sfields->At(1);
+ ArtField& throws_sfield = fields->At(1);
throws_sfield.SetDexFieldIndex(1);
throws_sfield.SetDeclaringClass(temp_klass.Get());
throws_sfield.SetAccessFlags(kAccStatic | kAccPublic | kAccFinal);
@@ -5455,7 +5462,6 @@ ObjPtr<mirror::Class> ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRun
// Consistency checks.
if (kIsDebugBuild) {
- CHECK(klass->GetIFieldsPtr() == nullptr);
CheckProxyConstructor(klass->GetDirectMethod(0, image_pointer_size_));
for (size_t i = 0; i < num_virtual_methods; ++i) {
@@ -5467,11 +5473,11 @@ ObjPtr<mirror::Class> ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRun
Handle<mirror::String> decoded_name = hs2.NewHandle(soa.Decode<mirror::String>(name));
std::string interfaces_field_name(StringPrintf("java.lang.Class[] %s.interfaces",
decoded_name->ToModifiedUtf8().c_str()));
- CHECK_EQ(ArtField::PrettyField(klass->GetStaticField(0)), interfaces_field_name);
+ CHECK_EQ(ArtField::PrettyField(klass->GetField(0)), interfaces_field_name);
std::string throws_field_name(StringPrintf("java.lang.Class[][] %s.throws",
decoded_name->ToModifiedUtf8().c_str()));
- CHECK_EQ(ArtField::PrettyField(klass->GetStaticField(1)), throws_field_name);
+ CHECK_EQ(ArtField::PrettyField(klass->GetField(1)), throws_field_name);
CHECK_EQ(klass.Get()->GetProxyInterfaces(),
soa.Decode<mirror::ObjectArray<mirror::Class>>(interfaces));
@@ -5576,7 +5582,7 @@ bool ClassLinker::CanWeInitializeClass(ObjPtr<mirror::Class> klass,
return false;
}
// Check if there are encoded static values needing initialization.
- if (klass->NumStaticFields() != 0) {
+ if (klass->HasStaticFields()) {
const dex::ClassDef* dex_class_def = klass->GetClassDef();
DCHECK(dex_class_def != nullptr);
if (dex_class_def->static_values_off_ != 0) {
@@ -5804,8 +5810,7 @@ bool ClassLinker::InitializeClass(Thread* self,
}
}
- const size_t num_static_fields = klass->NumStaticFields();
- if (num_static_fields > 0) {
+ if (klass->HasStaticFields()) {
const dex::ClassDef* dex_class_def = klass->GetClassDef();
CHECK(dex_class_def != nullptr);
StackHandleScope<2> hs(self);
@@ -5814,8 +5819,11 @@ bool ClassLinker::InitializeClass(Thread* self,
// Eagerly fill in static fields so that the we don't have to do as many expensive
// Class::FindStaticField in ResolveField.
- for (size_t i = 0; i < num_static_fields; ++i) {
- ArtField* field = klass->GetStaticField(i);
+ for (size_t i = 0; i < klass->NumFields(); ++i) {
+ ArtField* field = klass->GetField(i);
+ if (!field->IsStatic()) {
+ continue;
+ }
const uint32_t field_idx = field->GetDexFieldIndex();
ArtField* resolved_field = dex_cache->GetResolvedField(field_idx);
if (resolved_field == nullptr) {
@@ -6258,15 +6266,8 @@ bool ClassLinker::EnsureInitialized(Thread* self,
void ClassLinker::FixupTemporaryDeclaringClass(ObjPtr<mirror::Class> temp_class,
ObjPtr<mirror::Class> new_class) {
- DCHECK_EQ(temp_class->NumInstanceFields(), 0u);
- for (ArtField& field : new_class->GetIFields()) {
- if (field.GetDeclaringClass() == temp_class) {
- field.SetDeclaringClass(new_class);
- }
- }
-
- DCHECK_EQ(temp_class->NumStaticFields(), 0u);
- for (ArtField& field : new_class->GetSFields()) {
+ DCHECK_EQ(temp_class->NumFields(), 0u);
+ for (ArtField& field : new_class->GetFields()) {
if (field.GetDeclaringClass() == temp_class) {
field.SetDeclaringClass(new_class);
}
@@ -6413,8 +6414,7 @@ bool ClassLinker::LinkClass(Thread* self,
// may not see any references to the target space and clean the card for a class if another
// class had the same array pointer.
klass->SetMethodsPtrUnchecked(nullptr, 0, 0);
- klass->SetSFieldsPtrUnchecked(nullptr);
- klass->SetIFieldsPtrUnchecked(nullptr);
+ klass->SetFieldsPtrUnchecked(nullptr);
if (UNLIKELY(h_new_class == nullptr)) {
self->AssertPendingOOMException();
mirror::Class::SetStatus(klass, ClassStatus::kErrorUnresolved, self);
@@ -9283,9 +9283,7 @@ bool ClassLinker::LinkFieldsHelper::LinkFields(ClassLinker* class_linker,
bool is_static,
size_t* class_size) {
self->AllowThreadSuspension();
- const size_t num_fields = is_static ? klass->NumStaticFields() : klass->NumInstanceFields();
- LengthPrefixedArray<ArtField>* const fields = is_static ? klass->GetSFieldsPtr() :
- klass->GetIFieldsPtr();
+ LengthPrefixedArray<ArtField>* const fields = klass->GetFieldsPtr();
// Initialize field_offset
MemberOffset field_offset(0);
@@ -9301,7 +9299,8 @@ bool ClassLinker::LinkFieldsHelper::LinkFields(ClassLinker* class_linker,
}
}
- CHECK_EQ(num_fields == 0, fields == nullptr) << klass->PrettyClass();
+ size_t num_fields =
+ is_static ? klass->ComputeNumStaticFields() : klass->ComputeNumInstanceFields();
// we want a relatively stable order so that adding new fields
// minimizes disruption of C++ version such as Class and Method.
@@ -9341,8 +9340,11 @@ bool ClassLinker::LinkFieldsHelper::LinkFields(ClassLinker* class_linker,
size_t num_reference_fields = 0;
size_t primitive_fields_start = num_fields;
DCHECK_LE(num_fields, 1u << 16);
- for (size_t i = 0; i != num_fields; ++i) {
+ for (size_t i = 0; i != klass->NumFields(); ++i) {
ArtField* field = &fields->At(i);
+ if (field->IsStatic() != is_static) {
+ continue;
+ }
const char* descriptor = field->GetTypeDescriptor();
FieldTypeOrder field_type_order = FieldTypeOrderFromFirstDescriptorCharacter(descriptor[0]);
uint16_t field_index = dchecked_integral_cast<uint16_t>(i);
@@ -9491,8 +9493,8 @@ bool ClassLinker::LinkFieldsHelper::LinkFields(ClassLinker* class_linker,
// We know there are no non-reference fields in the Reference classes, and we know
// that 'referent' is alphabetically last, so this is easy...
CHECK_EQ(num_reference_fields, num_fields) << klass->PrettyClass();
- CHECK_STREQ(fields->At(num_fields - 1).GetName(), "referent")
- << klass->PrettyClass();
+ CHECK_STREQ(fields->At(klass->NumFields() - 2).GetName(), "referent");
+ CHECK_STREQ(fields->At(klass->NumFields() - 1).GetName(), "slowPathEnabled");
--num_reference_fields;
}
@@ -9550,8 +9552,11 @@ bool ClassLinker::LinkFieldsHelper::LinkFields(ClassLinker* class_linker,
num_reference_fields *
sizeof(mirror::HeapReference<mirror::Object>));
MemberOffset current_ref_offset = start_ref_offset;
- for (size_t i = 0; i < num_fields; i++) {
+ for (size_t i = 0; i < klass->NumFields(); i++) {
ArtField* field = &fields->At(i);
+ if (field->IsStatic() != is_static) {
+ continue;
+ }
VLOG(class_linker) << "LinkFields: " << (is_static ? "static" : "instance")
<< " class=" << klass->PrettyClass() << " field=" << field->PrettyField()
<< " offset=" << field->GetOffsetDuringLinking();
@@ -10182,19 +10187,16 @@ ArtField* ClassLinker::FindResolvedField(ObjPtr<mirror::Class> klass,
uint32_t field_idx,
bool is_static) {
DCHECK(dex_cache->GetClassLoader() == class_loader);
- ArtField* resolved = is_static ? klass->FindStaticField(dex_cache, field_idx)
- : klass->FindInstanceField(dex_cache, field_idx);
- if (resolved != nullptr &&
+ ArtField* resolved = klass->FindField(dex_cache, field_idx);
+ if (resolved == nullptr ||
+ is_static != resolved->IsStatic() ||
hiddenapi::ShouldDenyAccessToMember(resolved,
hiddenapi::AccessContext(class_loader, dex_cache),
hiddenapi::AccessMethod::kLinking)) {
- resolved = nullptr;
- }
-
- if (resolved != nullptr) {
- dex_cache->SetResolvedField(field_idx, resolved);
+ return nullptr;
}
+ dex_cache->SetResolvedField(field_idx, resolved);
return resolved;
}
@@ -10348,7 +10350,7 @@ ObjPtr<mirror::MethodHandle> ClassLinker::ResolveMethodHandleForField(
ArtField* target_field =
ResolveField(method_handle.field_or_method_idx_, referrer, is_static);
if (LIKELY(target_field != nullptr)) {
- DCHECK_EQ(is_static, target_field->IsStatic());
+ DCHECK_EQ(is_static, target_field->IsStatic()) << target_field->PrettyField();
ObjPtr<mirror::Class> target_class = target_field->GetDeclaringClass();
ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
if (UNLIKELY(!referring_class->CanAccessMember(target_class, target_field->GetAccessFlags()))) {