summaryrefslogtreecommitdiff
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
parentae13bd8a14183069642a5eed4793cf34f5a2eadc (diff)
Merge sFields and iFields.
Test: test.py Change-Id: Ib97fca637a8866a41a4389b150c6000d9fb6d99b
-rw-r--r--compiler/debug/elf_debug_info_writer.h7
-rw-r--r--compiler/driver/dex_compilation_unit.cc6
-rw-r--r--compiler/optimizing/inliner.cc5
-rw-r--r--compiler/optimizing/instruction_builder.cc2
-rw-r--r--compiler/optimizing/instruction_simplifier.cc2
-rw-r--r--compiler/optimizing/intrinsics.cc8
-rw-r--r--compiler/optimizing/reference_type_propagation.cc2
-rw-r--r--dex2oat/driver/compiler_driver.cc8
-rw-r--r--dex2oat/linker/image_writer.cc62
-rw-r--r--oatdump/oatdump.cc14
-rw-r--r--openjdkjvmti/ti_class.cc11
-rw-r--r--openjdkjvmti/ti_heap.cc64
-rw-r--r--openjdkjvmti/ti_redefine.cc77
-rw-r--r--perfetto_hprof/perfetto_hprof.cc5
-rw-r--r--runtime/arch/stub_test.cc10
-rw-r--r--runtime/art_field-inl.h28
-rw-r--r--runtime/class_linker.cc140
-rw-r--r--runtime/class_linker_test.cc96
-rw-r--r--runtime/gc/heap.cc5
-rw-r--r--runtime/gc/reference_processor.cc4
-rw-r--r--runtime/hidden_api_test.cc5
-rw-r--r--runtime/hprof/hprof.cc51
-rw-r--r--runtime/interpreter/unstarted_runtime.cc10
-rw-r--r--runtime/jni/jni_id_manager.cc38
-rw-r--r--runtime/method_handles.cc12
-rw-r--r--runtime/mirror/class-inl.h109
-rw-r--r--runtime/mirror/class-refvisitor-inl.h7
-rw-r--r--runtime/mirror/class.cc211
-rw-r--r--runtime/mirror/class.h64
-rw-r--r--runtime/mirror/dex_cache.cc5
-rw-r--r--runtime/mirror/dex_cache_test.cc18
-rw-r--r--runtime/mirror/field.cc14
-rw-r--r--runtime/mirror/object.cc8
-rw-r--r--runtime/native/java_lang_Class.cc6
-rw-r--r--runtime/proxy_test.cc17
-rw-r--r--runtime/runtime_image.cc40
-rw-r--r--test/906-iterate-heap/expected-stdout.txt24
-rw-r--r--test/913-heaps/expected-stdout.txt22
38 files changed, 543 insertions, 674 deletions
diff --git a/compiler/debug/elf_debug_info_writer.h b/compiler/debug/elf_debug_info_writer.h
index ae4cbd85ab..f2be4fb655 100644
--- a/compiler/debug/elf_debug_info_writer.h
+++ b/compiler/debug/elf_debug_info_writer.h
@@ -379,8 +379,11 @@ class ElfCompilationUnitWriter {
}
// Member variables.
- for (uint32_t i = 0, count = type->NumInstanceFields(); i < count; ++i) {
- ArtField* field = type->GetInstanceField(i);
+ for (uint32_t i = 0, count = type->NumFields(); i < count; ++i) {
+ ArtField* field = type->GetField(i);
+ if (field->IsStatic()) {
+ continue;
+ }
info_.StartTag(DW_TAG_member);
WriteName(field->GetName());
WriteLazyType(field->GetTypeDescriptor());
diff --git a/compiler/driver/dex_compilation_unit.cc b/compiler/driver/dex_compilation_unit.cc
index ccebfa9c07..fc139aa000 100644
--- a/compiler/driver/dex_compilation_unit.cc
+++ b/compiler/driver/dex_compilation_unit.cc
@@ -67,9 +67,9 @@ bool DexCompilationUnit::RequiresConstructorBarrier() const {
// Decoding class data can be slow, so iterate over fields of the compiling class if resolved.
ScopedObjectAccess soa(Thread::Current());
ObjPtr<mirror::Class> compiling_class = GetCompilingClass().Get();
- for (size_t i = 0, size = compiling_class->NumInstanceFields(); i != size; ++i) {
- ArtField* field = compiling_class->GetInstanceField(i);
- if (field->IsFinal()) {
+ for (size_t i = 0, size = compiling_class->NumFields(); i != size; ++i) {
+ ArtField* field = compiling_class->GetField(i);
+ if (field->IsFinal() && !field->IsStatic()) {
return true;
}
}
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index 5281346644..201841a5b4 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -804,7 +804,7 @@ HInliner::InlineCacheType HInliner::GetInlineCacheAOT(
HInstanceFieldGet* HInliner::BuildGetReceiverClass(ClassLinker* class_linker,
HInstruction* receiver,
uint32_t dex_pc) const {
- ArtField* field = GetClassRoot<mirror::Object>(class_linker)->GetInstanceField(0);
+ ArtField* field = GetClassRoot<mirror::Object>(class_linker)->GetField(0);
DCHECK_EQ(std::string(field->GetName()), "shadow$_klass_");
HInstanceFieldGet* result = new (graph_->GetAllocator()) HInstanceFieldGet(
receiver,
@@ -2452,8 +2452,7 @@ bool HInliner::ReturnTypeMoreSpecific(HInstruction* return_replacement,
return true;
} else if (return_replacement->IsInstanceFieldGet()) {
HInstanceFieldGet* field_get = return_replacement->AsInstanceFieldGet();
- if (field_get->GetFieldInfo().GetField() ==
- GetClassRoot<mirror::Object>()->GetInstanceField(0)) {
+ if (field_get->GetFieldInfo().GetField() == GetClassRoot<mirror::Object>()->GetField(0)) {
return true;
}
}
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index ba426b5694..c8086cff99 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -1634,7 +1634,7 @@ static bool HasTrivialClinit(ObjPtr<mirror::Class> klass, PointerSize pointer_si
REQUIRES_SHARED(Locks::mutator_lock_) {
// Check if the class has encoded fields that trigger bytecode execution.
// (Encoded fields are just a different representation of <clinit>.)
- if (klass->NumStaticFields() != 0u) {
+ if (klass->HasStaticFields()) {
DCHECK(klass->GetClassDef() != nullptr);
EncodedStaticFieldValueIterator it(klass->GetDexFile(), *klass->GetClassDef());
for (; it.HasNext(); it.Next()) {
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index 69a880c242..101808a193 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -1800,7 +1800,7 @@ static bool RecognizeAndSimplifyClassCheck(HCondition* condition) {
{
ScopedObjectAccess soa(Thread::Current());
- ArtField* field = GetClassRoot<mirror::Object>()->GetInstanceField(0);
+ ArtField* field = GetClassRoot<mirror::Object>()->GetField(0);
DCHECK_EQ(std::string(field->GetName()), "shadow$_klass_");
if (field_get->GetFieldInfo().GetField() != field) {
return false;
diff --git a/compiler/optimizing/intrinsics.cc b/compiler/optimizing/intrinsics.cc
index b87f6f3975..6b91cf515e 100644
--- a/compiler/optimizing/intrinsics.cc
+++ b/compiler/optimizing/intrinsics.cc
@@ -173,16 +173,16 @@ IntrinsicVisitor::ValueOfInfo IntrinsicVisitor::ComputeValueOfInfo(
MemberOffset IntrinsicVisitor::GetReferenceDisableIntrinsicOffset() {
ScopedObjectAccess soa(Thread::Current());
- // The "disableIntrinsic" is the first static field.
- ArtField* field = GetClassRoot<mirror::Reference>()->GetStaticField(0);
+ // The "disableIntrinsic" is the first field.
+ ArtField* field = GetClassRoot<mirror::Reference>()->GetField(0);
DCHECK_STREQ(field->GetName(), "disableIntrinsic");
return field->GetOffset();
}
MemberOffset IntrinsicVisitor::GetReferenceSlowPathEnabledOffset() {
ScopedObjectAccess soa(Thread::Current());
- // The "slowPathEnabled" is the second static field.
- ArtField* field = GetClassRoot<mirror::Reference>()->GetStaticField(1);
+ // The "slowPathEnabled" is the sixth field.
+ ArtField* field = GetClassRoot<mirror::Reference>()->GetField(5);
DCHECK_STREQ(field->GetName(), "slowPathEnabled");
return field->GetOffset();
}
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc
index 1eef0ce6d5..8ff1b89f9e 100644
--- a/compiler/optimizing/reference_type_propagation.cc
+++ b/compiler/optimizing/reference_type_propagation.cc
@@ -278,7 +278,7 @@ static void BoundTypeForClassCheck(HInstruction* check) {
{
ScopedObjectAccess soa(Thread::Current());
- ArtField* field = GetClassRoot<mirror::Object>()->GetInstanceField(0);
+ ArtField* field = GetClassRoot<mirror::Object>()->GetField(0);
DCHECK_EQ(std::string(field->GetName()), "shadow$_klass_");
if (field_get->GetFieldInfo().GetField() != field) {
return;
diff --git a/dex2oat/driver/compiler_driver.cc b/dex2oat/driver/compiler_driver.cc
index bbb70e4ef1..fc2d94a342 100644
--- a/dex2oat/driver/compiler_driver.cc
+++ b/dex2oat/driver/compiler_driver.cc
@@ -1404,10 +1404,9 @@ class ClinitImageUpdate {
} else if (can_include_in_image) {
// Check whether the class is initialized and has a clinit or static fields.
// Such classes must be kept too.
- if (klass->IsInitialized()) {
+ if (klass->IsInitialized() && !klass->IsArrayClass()) {
PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
- if (klass->FindClassInitializer(pointer_size) != nullptr ||
- klass->NumStaticFields() != 0) {
+ if (klass->FindClassInitializer(pointer_size) != nullptr || klass->HasStaticFields()) {
DCHECK(!Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(klass->GetDexCache()))
<< klass->PrettyDescriptor();
data_->image_classes_.push_back(data_->hs_.NewHandle(klass));
@@ -2275,8 +2274,9 @@ class InitializeClassVisitor : public CompilationVisitor {
// cannot be initialized, no need to proceed.
old_status = klass->GetStatus();
+ ClassAccessor accessor(klass->GetDexFile(), klass->GetDexClassDefIndex());
bool too_many_encoded_fields = (!is_boot_image && !is_boot_image_extension) &&
- klass->NumStaticFields() > kMaxEncodedFields;
+ accessor.NumStaticFields() > kMaxEncodedFields;
bool have_profile = (compiler_options.GetProfileCompilationInfo() != nullptr) &&
!compiler_options.GetProfileCompilationInfo()->IsEmpty();
diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc
index 179a0bb4f7..04bf4833cd 100644
--- a/dex2oat/linker/image_writer.cc
+++ b/dex2oat/linker/image_writer.cc
@@ -761,23 +761,12 @@ ImageWriter::Bin ImageWriter::GetImageBin(mirror::Object* object) {
// If the class's static fields are all final, put it into a separate bin
// since it's very likely it will stay clean.
- uint32_t num_static_fields = as_klass->NumStaticFields();
- if (num_static_fields == 0) {
+ auto fields = as_klass->GetFields();
+ bool all_final = std::all_of(fields.begin(),
+ fields.end(),
+ [](ArtField& f) { return !f.IsStatic() || f.IsFinal(); });
+ if (all_final) {
bin = Bin::kClassInitializedFinalStatics;
- } else {
- // Maybe all the statics are final?
- bool all_final = true;
- for (uint32_t i = 0; i < num_static_fields; ++i) {
- ArtField* field = as_klass->GetStaticField(i);
- if (!field->IsFinal()) {
- all_final = false;
- break;
- }
- }
-
- if (all_final) {
- bin = Bin::kClassInitializedFinalStatics;
- }
}
}
} else if (!klass->HasSuperClass()) {
@@ -1415,28 +1404,24 @@ void ImageWriter::RecordNativeRelocations(ObjPtr<mirror::Class> klass, size_t oa
// Extra consistency check: no boot loader classes should be left!
CHECK(!klass->IsBootStrapClassLoaded()) << klass->PrettyClass();
}
- LengthPrefixedArray<ArtField>* fields[] = {
- klass->GetSFieldsPtr(), klass->GetIFieldsPtr(),
- };
ImageInfo& image_info = GetImageInfo(oat_index);
- for (LengthPrefixedArray<ArtField>* cur_fields : fields) {
- // Total array length including header.
- if (cur_fields != nullptr) {
- // Forward the entire array at once.
- size_t offset = image_info.GetBinSlotSize(Bin::kArtField);
- DCHECK(!IsInBootImage(cur_fields));
- bool inserted =
- native_object_relocations_.insert(std::make_pair(
- cur_fields,
- NativeObjectRelocation{
- oat_index, offset, NativeObjectRelocationType::kArtFieldArray
- })).second;
- CHECK(inserted) << "Field array " << cur_fields << " already forwarded";
- const size_t size = LengthPrefixedArray<ArtField>::ComputeSize(cur_fields->size());
- offset += size;
- image_info.IncrementBinSlotSize(Bin::kArtField, size);
- DCHECK_EQ(offset, image_info.GetBinSlotSize(Bin::kArtField));
- }
+ LengthPrefixedArray<ArtField>* fields = klass->GetFieldsPtr();
+ // Total array length including header.
+ if (fields != nullptr) {
+ // Forward the entire array at once.
+ size_t offset = image_info.GetBinSlotSize(Bin::kArtField);
+ DCHECK(!IsInBootImage(fields));
+ bool inserted =
+ native_object_relocations_.insert(std::make_pair(
+ fields,
+ NativeObjectRelocation{
+ oat_index, offset, NativeObjectRelocationType::kArtFieldArray
+ })).second;
+ CHECK(inserted) << "Field array " << fields << " already forwarded";
+ const size_t size = LengthPrefixedArray<ArtField>::ComputeSize(fields->size());
+ offset += size;
+ image_info.IncrementBinSlotSize(Bin::kArtField, size);
+ DCHECK_EQ(offset, image_info.GetBinSlotSize(Bin::kArtField));
}
// Visit and assign offsets for methods.
size_t num_methods = klass->NumMethods();
@@ -3334,8 +3319,7 @@ T* ImageWriter::NativeLocationInImage(T* obj) {
ArtField* ImageWriter::NativeLocationInImage(ArtField* src_field) {
// Fields are not individually stored in the native relocation map. Use the field array.
ObjPtr<mirror::Class> declaring_class = src_field->GetDeclaringClass<kWithoutReadBarrier>();
- LengthPrefixedArray<ArtField>* src_fields =
- src_field->IsStatic() ? declaring_class->GetSFieldsPtr() : declaring_class->GetIFieldsPtr();
+ LengthPrefixedArray<ArtField>* src_fields = declaring_class->GetFieldsPtr();
DCHECK(src_fields != nullptr);
LengthPrefixedArray<ArtField>* dst_fields = NativeLocationInImage(src_fields);
DCHECK(dst_fields != nullptr);
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index feba70ff3a..1b0a3b552b 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -2075,8 +2075,10 @@ class ImageDumper {
if (super != nullptr) {
DumpFields(os, obj, super);
}
- for (ArtField& field : klass->GetIFields()) {
- PrintField(os, &field, obj);
+ for (ArtField& field : klass->GetFields()) {
+ if (!field.IsStatic()) {
+ PrintField(os, &field, obj);
+ }
}
}
@@ -2190,11 +2192,13 @@ class ImageDumper {
}
}
- if (klass->NumStaticFields() != 0) {
+ if (klass->HasStaticFields()) {
os << "STATICS:\n";
ScopedIndentation indent2(&vios_);
- for (ArtField& field : klass->GetSFields()) {
- PrintField(os, &field, field.GetDeclaringClass());
+ for (ArtField& field : klass->GetFields()) {
+ if (field.IsStatic()) {
+ PrintField(os, &field, field.GetDeclaringClass());
+ }
}
}
}
diff --git a/openjdkjvmti/ti_class.cc b/openjdkjvmti/ti_class.cc
index 5581bc2f02..40dde5755b 100644
--- a/openjdkjvmti/ti_class.cc
+++ b/openjdkjvmti/ti_class.cc
@@ -564,9 +564,8 @@ jvmtiError ClassUtil::GetClassFields(jvmtiEnv* env,
return ERR(NULL_POINTER);
}
- art::IterationRange<art::StrideIterator<art::ArtField>> ifields = klass->GetIFields();
- art::IterationRange<art::StrideIterator<art::ArtField>> sfields = klass->GetSFields();
- size_t array_size = klass->NumInstanceFields() + klass->NumStaticFields();
+ art::IterationRange<art::StrideIterator<art::ArtField>> fields = klass->GetFields();
+ size_t array_size = klass->NumFields();
unsigned char* out_ptr;
jvmtiError allocError = env->Allocate(array_size * sizeof(jfieldID), &out_ptr);
@@ -576,11 +575,7 @@ jvmtiError ClassUtil::GetClassFields(jvmtiEnv* env,
jfieldID* field_array = reinterpret_cast<jfieldID*>(out_ptr);
size_t array_idx = 0;
- for (art::ArtField& field : sfields) {
- field_array[array_idx] = art::jni::EncodeArtField(&field);
- ++array_idx;
- }
- for (art::ArtField& field : ifields) {
+ for (art::ArtField& field : fields) {
field_array[array_idx] = art::jni::EncodeArtField(&field);
++array_idx;
}
diff --git a/openjdkjvmti/ti_heap.cc b/openjdkjvmti/ti_heap.cc
index 80bfa0ff43..af74b67b17 100644
--- a/openjdkjvmti/ti_heap.cc
+++ b/openjdkjvmti/ti_heap.cc
@@ -352,43 +352,42 @@ class FieldVisitor {
// Now visit fields for the current klass.
- for (auto& static_field : klass->GetSFields()) {
- if (static_field.IsPrimitiveType()) {
- if (static_prim_visitor(obj,
- klass,
- static_field,
- field_index,
- user_data_)) {
- return true;
- }
- } else {
- if (static_ref_visitor(obj,
- klass,
- static_field,
- field_index,
- user_data_)) {
- return true;
- }
- }
- field_index++;
- }
-
- for (auto& instance_field : klass->GetIFields()) {
- if (instance_field.IsPrimitiveType()) {
- if (instance_prim_visitor(obj,
+ for (auto& field : klass->GetFields()) {
+ if (field.IsStatic()) {
+ if (field.IsPrimitiveType()) {
+ if (static_prim_visitor(obj,
klass,
- instance_field,
+ field,
field_index,
user_data_)) {
- return true;
- }
- } else {
- if (instance_ref_visitor(obj,
+ return true;
+ }
+ } else {
+ if (static_ref_visitor(obj,
klass,
- instance_field,
+ field,
field_index,
user_data_)) {
- return true;
+ return true;
+ }
+ }
+ } else {
+ if (field.IsPrimitiveType()) {
+ if (instance_prim_visitor(obj,
+ klass,
+ field,
+ field_index,
+ user_data_)) {
+ return true;
+ }
+ } else {
+ if (instance_ref_visitor(obj,
+ klass,
+ field,
+ field_index,
+ user_data_)) {
+ return true;
+ }
}
}
field_index++;
@@ -458,8 +457,7 @@ class FieldVisitor {
auto visitor = [&count](art::ObjPtr<art::mirror::Class> inf_klass)
REQUIRES_SHARED(art::Locks::mutator_lock_) {
DCHECK(inf_klass->IsInterface());
- DCHECK_EQ(0u, inf_klass->NumInstanceFields());
- count += inf_klass->NumStaticFields();
+ count += inf_klass->NumFields();
};
RecursiveInterfaceVisit<decltype(visitor)>::VisitStatic(art::Thread::Current(), klass, visitor);
diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc
index 8e11d592e5..d2e022fd14 100644
--- a/openjdkjvmti/ti_redefine.cc
+++ b/openjdkjvmti/ti_redefine.cc
@@ -2585,21 +2585,18 @@ void Redefiner::ClassRedefinition::UpdateMethods(art::ObjPtr<art::mirror::Class>
}
void Redefiner::ClassRedefinition::UpdateFields(art::ObjPtr<art::mirror::Class> mclass) {
- // TODO The IFields & SFields pointers should be combined like the methods_ arrays were.
- for (auto fields_iter : {mclass->GetIFields(), mclass->GetSFields()}) {
- for (art::ArtField& field : fields_iter) {
- const art::dex::TypeId* new_declaring_id =
- dex_file_->FindTypeId(field.GetDeclaringClassDescriptorView());
- const art::dex::StringId* new_name_id = dex_file_->FindStringId(field.GetName());
- const art::dex::TypeId* new_type_id = dex_file_->FindTypeId(field.GetTypeDescriptorView());
- CHECK(new_name_id != nullptr && new_type_id != nullptr && new_declaring_id != nullptr);
- const art::dex::FieldId* new_field_id =
- dex_file_->FindFieldId(*new_declaring_id, *new_name_id, *new_type_id);
- CHECK(new_field_id != nullptr);
- uint32_t new_field_index = dex_file_->GetIndexForFieldId(*new_field_id);
- // We only need to update the index since the other data in the ArtField cannot be updated.
- field.SetDexFieldIndex(new_field_index);
- }
+ for (art::ArtField& field : mclass->GetFields()) {
+ const art::dex::TypeId* new_declaring_id =
+ dex_file_->FindTypeId(field.GetDeclaringClassDescriptorView());
+ const art::dex::StringId* new_name_id = dex_file_->FindStringId(field.GetName());
+ const art::dex::TypeId* new_type_id = dex_file_->FindTypeId(field.GetTypeDescriptorView());
+ CHECK(new_name_id != nullptr && new_type_id != nullptr && new_declaring_id != nullptr);
+ const art::dex::FieldId* new_field_id =
+ dex_file_->FindFieldId(*new_declaring_id, *new_name_id, *new_type_id);
+ CHECK(new_field_id != nullptr);
+ uint32_t new_field_index = dex_file_->GetIndexForFieldId(*new_field_id);
+ // We only need to update the index since the other data in the ArtField cannot be updated.
+ field.SetDexFieldIndex(new_field_index);
}
}
@@ -2609,11 +2606,10 @@ void Redefiner::ClassRedefinition::CollectNewFieldAndMethodMappings(
std::map<art::ArtField*, art::ArtField*>* field_map) {
for (auto [new_cls, old_cls] :
art::ZipLeft(data.GetNewClasses()->Iterate(), data.GetOldClasses()->Iterate())) {
- for (art::ArtField& f : old_cls->GetSFields()) {
- (*field_map)[&f] = new_cls->FindDeclaredStaticField(f.GetName(), f.GetTypeDescriptor());
- }
- for (art::ArtField& f : old_cls->GetIFields()) {
- (*field_map)[&f] = new_cls->FindDeclaredInstanceField(f.GetName(), f.GetTypeDescriptor());
+ for (art::ArtField& f : old_cls->GetFields()) {
+ (*field_map)[&f] = f.IsStatic()
+ ? new_cls->FindDeclaredStaticField(f.GetName(), f.GetTypeDescriptor())
+ : new_cls->FindDeclaredInstanceField(f.GetName(), f.GetTypeDescriptor());
}
auto new_methods = new_cls->GetMethods(art::kRuntimePointerSize);
for (art::ArtMethod& m : old_cls->GetMethods(art::kRuntimePointerSize)) {
@@ -2673,12 +2669,14 @@ static void CopyFields(bool is_static,
DCHECK(!source_class->IsObjectClass() && !target_class->IsObjectClass())
<< "Should not be overriding object class fields. Target: " << target_class->PrettyClass()
<< " Source: " << source_class->PrettyClass();
- for (art::ArtField& f : (is_static ? source_class->GetSFields() : source_class->GetIFields())) {
- art::ArtField* new_field =
- (is_static ? target_class->FindDeclaredStaticField(f.GetName(), f.GetTypeDescriptor())
- : target_class->FindDeclaredInstanceField(f.GetName(), f.GetTypeDescriptor()));
- CHECK(new_field != nullptr) << "could not find new version of " << f.PrettyField();
- CopyField(target, new_field, source, f);
+ for (art::ArtField& f : source_class->GetFields()) {
+ if (f.IsStatic() == is_static) {
+ art::ArtField* new_field =
+ (is_static ? target_class->FindDeclaredStaticField(f.GetName(), f.GetTypeDescriptor())
+ : target_class->FindDeclaredInstanceField(f.GetName(), f.GetTypeDescriptor()));
+ CHECK(new_field != nullptr) << "could not find new version of " << f.PrettyField();
+ CopyField(target, new_field, source, f);
+ }
}
if (!is_static && !target_class->GetSuperClass()->IsObjectClass()) {
CopyFields(
@@ -2719,8 +2717,10 @@ static void ClearFields(bool is_static,
art::ObjPtr<art::mirror::Class> target_class)
REQUIRES(art::Locks::mutator_lock_) {
DCHECK(!target_class->IsObjectClass());
- for (art::ArtField& f : (is_static ? target_class->GetSFields() : target_class->GetIFields())) {
- ClearField(target, f);
+ for (art::ArtField& f : target_class->GetFields()) {
+ if (f.IsStatic() == is_static) {
+ ClearField(target, f);
+ }
}
if (!is_static && !target_class->GetSuperClass()->IsObjectClass()) {
ClearFields(is_static, target, target_class->GetSuperClass());
@@ -2860,27 +2860,16 @@ void Redefiner::ClassRedefinition::UpdateClassStructurally(const RedefinitionDat
});
} else {
auto pred = [&](art::ArtField& f) REQUIRES(art::Locks::mutator_lock_) {
- return std::string_view(f.GetName()) == std::string_view(field_or_method->GetName()) &&
- std::string_view(f.GetTypeDescriptor()) ==
- std::string_view(field_or_method->GetTypeDescriptor());
+ return f.GetNameView() == field_or_method->GetNameView() &&
+ f.GetTypeDescriptorView() == field_or_method->GetTypeDescriptorView();
};
- if (field_or_method->IsStatic()) {
- return std::any_of(
- replacement_classes_iter.begin(),
- replacement_classes_iter.end(),
- [&](art::ObjPtr<art::mirror::Class> cand) REQUIRES(art::Locks::mutator_lock_) {
- auto sfields = cand->GetSFields();
- return std::find_if(sfields.begin(), sfields.end(), pred) != sfields.end();
- });
- } else {
- return std::any_of(
+ return std::any_of(
replacement_classes_iter.begin(),
replacement_classes_iter.end(),
[&](art::ObjPtr<art::mirror::Class> cand) REQUIRES(art::Locks::mutator_lock_) {
- auto ifields = cand->GetIFields();
- return std::find_if(ifields.begin(), ifields.end(), pred) != ifields.end();
+ auto fields = cand->GetFields();
+ return std::find_if(fields.begin(), fields.end(), pred) != fields.end();
});
- }
}
};
// TODO Performing 2 stack-walks back to back isn't the greatest. We might want to try to combine
diff --git a/perfetto_hprof/perfetto_hprof.cc b/perfetto_hprof/perfetto_hprof.cc
index 7379fd66c9..0602437383 100644
--- a/perfetto_hprof/perfetto_hprof.cc
+++ b/perfetto_hprof/perfetto_hprof.cc
@@ -568,8 +568,9 @@ uint64_t GetObjectId(const art::mirror::Object* obj) {
template <typename F>
void ForInstanceReferenceField(art::mirror::Class* klass, F fn) NO_THREAD_SAFETY_ANALYSIS {
- for (art::ArtField& af : klass->GetIFields()) {
- if (af.IsPrimitiveType() ||
+ for (art::ArtField& af : klass->GetFields()) {
+ if (af.IsStatic() ||
+ af.IsPrimitiveType() ||
af.GetOffset().Uint32Value() == art::mirror::Object::ClassOffset().Uint32Value()) {
continue;
}
diff --git a/runtime/arch/stub_test.cc b/runtime/arch/stub_test.cc
index 95d21e0eb7..1dd8c83499 100644
--- a/runtime/arch/stub_test.cc
+++ b/runtime/arch/stub_test.cc
@@ -1565,7 +1565,10 @@ static void TestFields(Thread* self, StubTest* test, Primitive::Type test_type)
// Play with it...
// Static fields.
- for (ArtField& f : c->GetSFields()) {
+ for (ArtField& f : c->GetFields()) {
+ if (!f.IsStatic()) {
+ continue;
+ }
Primitive::Type type = f.GetTypeAsPrimitiveType();
if (test_type != type) {
continue;
@@ -1601,7 +1604,10 @@ static void TestFields(Thread* self, StubTest* test, Primitive::Type test_type)
}
// Instance fields.
- for (ArtField& f : c->GetIFields()) {
+ for (ArtField& f : c->GetFields()) {
+ if (f.IsStatic()) {
+ continue;
+ }
Primitive::Type type = f.GetTypeAsPrimitiveType();
if (test_type != type) {
continue;
diff --git a/runtime/art_field-inl.h b/runtime/art_field-inl.h
index dd86e68164..8557b13ae6 100644
--- a/runtime/art_field-inl.h
+++ b/runtime/art_field-inl.h
@@ -425,19 +425,20 @@ inline ObjPtr<mirror::String> ArtField::ResolveNameString() {
template <bool kExactOffset>
static inline ArtField* FindFieldWithOffset(
const IterationRange<StrideIterator<ArtField>>& fields,
- uint32_t field_offset) REQUIRES_SHARED(Locks::mutator_lock_) {
+ uint32_t field_offset,
+ bool is_static) REQUIRES_SHARED(Locks::mutator_lock_) {
for (ArtField& field : fields) {
- if (kExactOffset) {
- if (field.GetOffset().Uint32Value() == field_offset) {
- return &field;
- }
- } else {
- const uint32_t offset = field.GetOffset().Uint32Value();
- Primitive::Type type = field.GetTypeAsPrimitiveType();
- const size_t field_size = Primitive::ComponentSize(type);
- DCHECK_GT(field_size, 0u);
- if (offset <= field_offset && field_offset < offset + field_size) {
+ if (field.IsStatic() == is_static) {
+ if (kExactOffset && field.GetOffset().Uint32Value() == field_offset) {
return &field;
+ } else {
+ const uint32_t offset = field.GetOffset().Uint32Value();
+ Primitive::Type type = field.GetTypeAsPrimitiveType();
+ const size_t field_size = Primitive::ComponentSize(type);
+ DCHECK_GT(field_size, 0u);
+ if (offset <= field_offset && field_offset < offset + field_size) {
+ return &field;
+ }
}
}
}
@@ -448,7 +449,8 @@ template <bool kExactOffset, VerifyObjectFlags kVerifyFlags, ReadBarrierOption k
inline ArtField* ArtField::FindInstanceFieldWithOffset(ObjPtr<mirror::Class> klass,
uint32_t field_offset) {
DCHECK(klass != nullptr);
- ArtField* field = FindFieldWithOffset<kExactOffset>(klass->GetIFields(), field_offset);
+ ArtField* field = FindFieldWithOffset<kExactOffset>(
+ klass->GetFields(), field_offset, /* is_static= */ false);
if (field != nullptr) {
return field;
}
@@ -464,7 +466,7 @@ template <bool kExactOffset>
inline ArtField* ArtField::FindStaticFieldWithOffset(ObjPtr<mirror::Class> klass,
uint32_t field_offset) {
DCHECK(klass != nullptr);
- return FindFieldWithOffset<kExactOffset>(klass->GetSFields(), field_offset);
+ return FindFieldWithOffset<kExactOffset>(klass->GetFields(), field_offset, /* is_static= */ true);
}
inline ObjPtr<mirror::ClassLoader> ArtField::GetClassLoader() {
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()))) {
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 5d5d025050..1176bb133e 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -110,8 +110,7 @@ class ClassLinkerTest : public CommonRuntimeTest {
EXPECT_FALSE(primitive->IsSynthetic());
EXPECT_EQ(0U, primitive->NumDirectMethods());
EXPECT_EQ(0U, primitive->NumVirtualMethods());
- EXPECT_EQ(0U, primitive->NumInstanceFields());
- EXPECT_EQ(0U, primitive->NumStaticFields());
+ EXPECT_EQ(0U, primitive->NumFields());
EXPECT_EQ(0U, primitive->NumDirectInterfaces());
EXPECT_FALSE(primitive->HasVTable());
EXPECT_EQ(0, primitive->GetIfTableCount());
@@ -156,13 +155,12 @@ class ClassLinkerTest : public CommonRuntimeTest {
EXPECT_FALSE(JavaLangObject->IsSynthetic());
EXPECT_EQ(4U, JavaLangObject->NumDirectMethods());
EXPECT_EQ(11U, JavaLangObject->NumVirtualMethods());
- EXPECT_EQ(2U, JavaLangObject->NumInstanceFields());
- EXPECT_STREQ(JavaLangObject->GetInstanceField(0)->GetName(),
- "shadow$_klass_");
- EXPECT_STREQ(JavaLangObject->GetInstanceField(1)->GetName(),
- "shadow$_monitor_");
+ EXPECT_EQ(2U, JavaLangObject->NumFields());
+ EXPECT_STREQ(JavaLangObject->GetField(0)->GetName(), "shadow$_klass_");
+ EXPECT_FALSE(JavaLangObject->GetField(0)->IsStatic());
+ EXPECT_STREQ(JavaLangObject->GetField(1)->GetName(), "shadow$_monitor_");
+ EXPECT_FALSE(JavaLangObject->GetField(1)->IsStatic());
- EXPECT_EQ(0U, JavaLangObject->NumStaticFields());
EXPECT_EQ(0U, JavaLangObject->NumDirectInterfaces());
PointerSize pointer_size = class_linker_->GetImagePointerSize();
@@ -220,8 +218,7 @@ class ClassLinkerTest : public CommonRuntimeTest {
EXPECT_FALSE(array->IsSynthetic());
EXPECT_EQ(0U, array->NumDirectMethods());
EXPECT_EQ(0U, array->NumVirtualMethods());
- EXPECT_EQ(0U, array->NumInstanceFields());
- EXPECT_EQ(0U, array->NumStaticFields());
+ EXPECT_EQ(0U, array->NumFields());
EXPECT_EQ(2U, array->NumDirectInterfaces());
EXPECT_TRUE(array->ShouldHaveImt());
EXPECT_TRUE(array->ShouldHaveEmbeddedVTable());
@@ -343,27 +340,23 @@ class ClassLinkerTest : public CommonRuntimeTest {
<< "declaring class: " << method.GetDeclaringClass()->PrettyClass();
}
- for (size_t i = 0; i < klass->NumInstanceFields(); i++) {
- ArtField* field = klass->GetInstanceField(i);
+ for (size_t i = 0; i < klass->NumFields(); i++) {
+ ArtField* field = klass->GetField(i);
AssertField(klass.Get(), field);
- EXPECT_FALSE(field->IsStatic());
- }
-
- for (size_t i = 0; i < klass->NumStaticFields(); i++) {
- ArtField* field = klass->GetStaticField(i);
- AssertField(klass.Get(), field);
- EXPECT_TRUE(field->IsStatic());
}
// Confirm that all instances field offsets are packed together at the start.
- EXPECT_GE(klass->NumInstanceFields(), klass->NumReferenceInstanceFields());
+ EXPECT_GE(klass->ComputeNumInstanceFields(), klass->NumReferenceInstanceFields());
MemberOffset start_ref_offset = klass->GetFirstReferenceInstanceFieldOffset();
MemberOffset end_ref_offset(start_ref_offset.Uint32Value() +
klass->NumReferenceInstanceFields() *
sizeof(mirror::HeapReference<mirror::Object>));
MemberOffset current_ref_offset = start_ref_offset;
- for (size_t i = 0; i < klass->NumInstanceFields(); i++) {
- ArtField* field = klass->GetInstanceField(i);
+ for (size_t i = 0; i < klass->NumFields(); i++) {
+ ArtField* field = klass->GetField(i);
+ if (field->IsStatic()) {
+ continue;
+ }
ObjPtr<mirror::Class> field_type = field->ResolveType();
ASSERT_TRUE(field_type != nullptr);
if (!field->IsPrimitiveType()) {
@@ -499,7 +492,8 @@ struct CheckOffsets {
}
}
- size_t num_fields = is_static ? klass->NumStaticFields() : klass->NumInstanceFields();
+ size_t num_fields =
+ is_static ? klass->ComputeNumStaticFields() : klass->ComputeNumInstanceFields();
if (offsets.size() != num_fields) {
LOG(ERROR) << "Field count mismatch:"
<< " class=" << class_descriptor
@@ -508,17 +502,25 @@ struct CheckOffsets {
error = true;
}
+ size_t j = 0;
for (size_t i = 0; i < offsets.size(); i++) {
- ArtField* field = is_static ? klass->GetStaticField(i) : klass->GetInstanceField(i);
+ ArtField* field = nullptr;
+ do {
+ field = klass->GetField(j++);
+ } while (field->IsStatic() != is_static);
std::string_view field_name(field->GetName());
if (field_name != offsets[i].java_name) {
error = true;
}
}
+ j = 0;
if (error) {
for (size_t i = 0; i < offsets.size(); i++) {
CheckOffset& offset = offsets[i];
- ArtField* field = is_static ? klass->GetStaticField(i) : klass->GetInstanceField(i);
+ ArtField* field = nullptr;
+ do {
+ field = klass->GetField(j++);
+ } while (field->IsStatic() != is_static);
std::string_view field_name(field->GetName());
if (field_name != offsets[i].java_name) {
LOG(ERROR) << "JAVA FIELD ORDER MISMATCH NEXT LINE:";
@@ -530,17 +532,25 @@ struct CheckOffsets {
}
}
+ j = 0;
for (size_t i = 0; i < offsets.size(); i++) {
CheckOffset& offset = offsets[i];
- ArtField* field = is_static ? klass->GetStaticField(i) : klass->GetInstanceField(i);
+ ArtField* field = nullptr;
+ do {
+ field = klass->GetField(j++);
+ } while (field->IsStatic() != is_static);
if (field->GetOffset().Uint32Value() != offset.cpp_offset) {
error = true;
}
}
+ j = 0;
if (error) {
for (size_t i = 0; i < offsets.size(); i++) {
CheckOffset& offset = offsets[i];
- ArtField* field = is_static ? klass->GetStaticField(i) : klass->GetInstanceField(i);
+ ArtField* field = nullptr;
+ do {
+ field = klass->GetField(j++);
+ } while (field->IsStatic() != is_static);
if (field->GetOffset().Uint32Value() != offset.cpp_offset) {
LOG(ERROR) << "OFFSET MISMATCH NEXT LINE:";
}
@@ -583,7 +593,7 @@ struct ClassOffsets : public CheckOffsets<mirror::Class> {
addOffset(OFFSETOF_MEMBER(mirror::Class, dex_class_def_idx_), "dexClassDefIndex");
addOffset(OFFSETOF_MEMBER(mirror::Class, dex_type_idx_), "dexTypeIndex");
addOffset(OFFSETOF_MEMBER(mirror::Class, ext_data_), "extData");
- addOffset(OFFSETOF_MEMBER(mirror::Class, ifields_), "iFields");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, fields_), "fields");
addOffset(OFFSETOF_MEMBER(mirror::Class, iftable_), "ifTable");
addOffset(OFFSETOF_MEMBER(mirror::Class, methods_), "methods");
addOffset(OFFSETOF_MEMBER(mirror::Class, name_), "name");
@@ -597,7 +607,6 @@ struct ClassOffsets : public CheckOffsets<mirror::Class> {
addOffset(OFFSETOF_MEMBER(mirror::Class, primitive_type_), "primitiveType");
addOffset(OFFSETOF_MEMBER(mirror::Class, reference_instance_offsets_),
"referenceInstanceOffsets");
- addOffset(OFFSETOF_MEMBER(mirror::Class, sfields_), "sFields");
addOffset(OFFSETOF_MEMBER(mirror::Class, status_), "status");
addOffset(OFFSETOF_MEMBER(mirror::Class, super_class_), "superClass");
addOffset(OFFSETOF_MEMBER(mirror::Class, virtual_methods_offset_), "virtualMethodsOffset");
@@ -975,8 +984,7 @@ TEST_F(ClassLinkerTest, FindClass) {
EXPECT_FALSE(MyClass->IsSynthetic());
EXPECT_EQ(1U, MyClass->NumDirectMethods());
EXPECT_EQ(0U, MyClass->NumVirtualMethods());
- EXPECT_EQ(0U, MyClass->NumInstanceFields());
- EXPECT_EQ(0U, MyClass->NumStaticFields());
+ EXPECT_EQ(0U, MyClass->NumFields());
EXPECT_EQ(0U, MyClass->NumDirectInterfaces());
EXPECT_OBJ_PTR_EQ(JavaLangObject->GetClass()->GetClass(), MyClass->GetClass()->GetClass());
@@ -1137,30 +1145,6 @@ TEST_F(ClassLinkerTest, ValidatePrimitiveArrayElementsOffset) {
// Take it as given that bytes and booleans have byte alignment
}
-TEST_F(ClassLinkerTest, ValidateBoxedTypes) {
- // Validate that the "value" field is always the 0th field in each of java.lang's box classes.
- // This lets UnboxPrimitive avoid searching for the field by name at runtime.
- ScopedObjectAccess soa(Thread::Current());
- ScopedNullHandle<mirror::ClassLoader> class_loader;
- ObjPtr<mirror::Class> c;
- c = FindClass("Ljava/lang/Boolean;", class_loader);
- EXPECT_STREQ("value", c->GetIFieldsPtr()->At(0).GetName());
- c = FindClass("Ljava/lang/Byte;", class_loader);
- EXPECT_STREQ("value", c->GetIFieldsPtr()->At(0).GetName());
- c = FindClass("Ljava/lang/Character;", class_loader);
- EXPECT_STREQ("value", c->GetIFieldsPtr()->At(0).GetName());
- c = FindClass("Ljava/lang/Double;", class_loader);
- EXPECT_STREQ("value", c->GetIFieldsPtr()->At(0).GetName());
- c = FindClass("Ljava/lang/Float;", class_loader);
- EXPECT_STREQ("value", c->GetIFieldsPtr()->At(0).GetName());
- c = FindClass("Ljava/lang/Integer;", class_loader);
- EXPECT_STREQ("value", c->GetIFieldsPtr()->At(0).GetName());
- c = FindClass("Ljava/lang/Long;", class_loader);
- EXPECT_STREQ("value", c->GetIFieldsPtr()->At(0).GetName());
- c = FindClass("Ljava/lang/Short;", class_loader);
- EXPECT_STREQ("value", c->GetIFieldsPtr()->At(0).GetName());
-}
-
TEST_F(ClassLinkerTest, TwoClassLoadersOneClass) {
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<3> hs(soa.Self());
@@ -1189,7 +1173,7 @@ TEST_F(ClassLinkerTest, StaticFields) {
ArtMethod* clinit = statics->FindClassMethod("<clinit>", "()V", kRuntimePointerSize);
EXPECT_TRUE(clinit == nullptr);
- EXPECT_EQ(9U, statics->NumStaticFields());
+ EXPECT_EQ(9U, statics->NumFields());
ArtField* s0 = statics->FindStaticField("s0", "Z");
EXPECT_EQ(s0->GetTypeAsPrimitiveType(), Primitive::kPrimBoolean);
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 7ea675d4cf..5ceeeb75af 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -3375,8 +3375,9 @@ class VerifyReferenceCardVisitor {
if (!obj->IsObjectArray()) {
ObjPtr<mirror::Class> klass = is_static ? obj->AsClass() : obj->GetClass();
CHECK(klass != nullptr);
- for (ArtField& field : (is_static ? klass->GetSFields() : klass->GetIFields())) {
- if (field.GetOffset().Int32Value() == offset.Int32Value()) {
+ for (ArtField& field : klass->GetFields()) {
+ if (is_static == field.IsStatic() &&
+ field.GetOffset().Int32Value() == offset.Int32Value()) {
LOG(ERROR) << (is_static ? "Static " : "") << "field in the live stack is "
<< field.PrettyField();
break;
diff --git a/runtime/gc/reference_processor.cc b/runtime/gc/reference_processor.cc
index cb777c895c..c799f5443b 100644
--- a/runtime/gc/reference_processor.cc
+++ b/runtime/gc/reference_processor.cc
@@ -54,8 +54,8 @@ ReferenceProcessor::ReferenceProcessor()
static inline MemberOffset GetSlowPathFlagOffset(ObjPtr<mirror::Class> reference_class)
REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(reference_class == GetClassRoot<mirror::Reference>());
- // Second static field
- ArtField* field = reference_class->GetStaticField(1);
+ ArtField* field = reference_class->GetField(reference_class->NumFields() - 1);
+ DCHECK(field->IsStatic());
DCHECK_STREQ(field->GetName(), "slowPathEnabled");
return field->GetOffset();
}
diff --git a/runtime/hidden_api_test.cc b/runtime/hidden_api_test.cc
index b16c42f1a7..444ad0bd48 100644
--- a/runtime/hidden_api_test.cc
+++ b/runtime/hidden_api_test.cc
@@ -651,14 +651,15 @@ TEST_F(HiddenApiTest, CheckMemberSignatureForProxyClass) {
// Find the "interfaces" static field. This is generated for all proxies.
ArtField* field = nullptr;
- for (size_t i = 0; i < proxyClass->NumStaticFields(); ++i) {
- ArtField* f = proxyClass->GetStaticField(i);
+ for (size_t i = 0; i < proxyClass->NumFields(); ++i) {
+ ArtField* f = proxyClass->GetField(i);
if (strcmp("interfaces", f->GetName()) == 0) {
field = f;
break;
}
}
ASSERT_TRUE(field != nullptr);
+ ASSERT_TRUE(field->IsStatic());
// Test the signature. We expect the signature from the interface class.
std::ostringstream ss_method;
diff --git a/runtime/hprof/hprof.cc b/runtime/hprof/hprof.cc
index f77370d3d4..885112c342 100644
--- a/runtime/hprof/hprof.cc
+++ b/runtime/hprof/hprof.cc
@@ -1191,7 +1191,7 @@ void Hprof::DumpHeapClass(mirror::Class* klass) {
// For other overhead (currently only the embedded vtable), we will generate a synthetic
// byte array (or field[s] in case the overhead size is of reference size or less).
- const size_t num_static_fields = klass->NumStaticFields();
+ const size_t num_static_fields = klass->ComputeNumStaticFields();
// Total class size:
// * class instance fields (including Object instance fields)
@@ -1212,10 +1212,12 @@ void Hprof::DumpHeapClass(mirror::Class* klass) {
// Tools (ahat/Studio) will count the static fields and account for them in the class size. We
// must thus subtract them from base_overhead_size or they will be double-counted.
size_t class_static_fields_size = 0;
- for (ArtField& class_static_field : klass->GetSFields()) {
- size_t size = 0;
- SignatureToBasicTypeAndSize(class_static_field.GetTypeDescriptor(), &size);
- class_static_fields_size += size;
+ for (ArtField& class_field : klass->GetFields()) {
+ if (class_field.IsStatic()) {
+ size_t size = 0;
+ SignatureToBasicTypeAndSize(class_field.GetTypeDescriptor(), &size);
+ class_static_fields_size += size;
+ }
}
CHECK_GE(base_overhead_size, class_static_fields_size);
@@ -1284,8 +1286,8 @@ void Hprof::DumpHeapClass(mirror::Class* klass) {
mirror::Class* class_class = klass->GetClass();
DCHECK(class_class->GetSuperClass()->IsObjectClass());
- const size_t static_fields_reported = class_class->NumInstanceFields()
- + class_class->GetSuperClass()->NumInstanceFields()
+ const size_t static_fields_reported = class_class->ComputeNumInstanceFields()
+ + class_class->GetSuperClass()->ComputeNumInstanceFields()
+ java_heap_overhead_field_count
+ num_static_fields;
__ AddU2(dchecked_integral_cast<uint16_t>(static_fields_reported));
@@ -1373,11 +1375,15 @@ void Hprof::DumpHeapClass(mirror::Class* klass) {
auto class_instance_field_name_fn = [](ArtField& field) REQUIRES_SHARED(Locks::mutator_lock_) {
return std::string("$class$") + field.GetName();
};
- for (ArtField& class_instance_field : class_class->GetIFields()) {
- static_field_writer(class_instance_field, class_instance_field_name_fn);
+ for (ArtField& class_field : class_class->GetFields()) {
+ if (!class_field.IsStatic()) {
+ static_field_writer(class_field, class_instance_field_name_fn);
+ }
}
- for (ArtField& object_instance_field : class_class->GetSuperClass()->GetIFields()) {
- static_field_writer(object_instance_field, class_instance_field_name_fn);
+ for (ArtField& object_field : class_class->GetSuperClass()->GetFields()) {
+ if (!object_field.IsStatic()) {
+ static_field_writer(object_field, class_instance_field_name_fn);
+ }
}
}
@@ -1385,13 +1391,15 @@ void Hprof::DumpHeapClass(mirror::Class* klass) {
auto class_static_field_name_fn = [](ArtField& field) REQUIRES_SHARED(Locks::mutator_lock_) {
return field.GetName();
};
- for (ArtField& class_static_field : klass->GetSFields()) {
- static_field_writer(class_static_field, class_static_field_name_fn);
+ for (ArtField& class_field : klass->GetFields()) {
+ if (class_field.IsStatic()) {
+ static_field_writer(class_field, class_static_field_name_fn);
+ }
}
}
// Instance fields for this class (no superclass fields)
- int iFieldCount = klass->NumInstanceFields();
+ int iFieldCount = klass->ComputeNumInstanceFields();
// add_internal_runtime_objects is only for classes that may retain objects live through means
// other than fields. It is never the case for strings.
const bool add_internal_runtime_objects = AddRuntimeInternalObjectsField(klass);
@@ -1400,8 +1408,11 @@ void Hprof::DumpHeapClass(mirror::Class* klass) {
} else {
__ AddU2((uint16_t)iFieldCount);
}
- for (int i = 0; i < iFieldCount; ++i) {
- ArtField* f = klass->GetInstanceField(i);
+ for (uint32_t i = 0; i < klass->NumFields(); ++i) {
+ ArtField* f = klass->GetField(i);
+ if (f->IsStatic()) {
+ continue;
+ }
__ AddStringId(LookupStringId(f->GetName()));
HprofBasicType t = SignatureToBasicTypeAndSize(f->GetTypeDescriptor(), nullptr);
__ AddU1(t);
@@ -1487,9 +1498,11 @@ void Hprof::DumpHeapInstanceObject(mirror::Object* obj,
// Write the instance data; fields for this class, followed by super class fields, and so on.
do {
- const size_t instance_fields = klass->NumInstanceFields();
- for (size_t i = 0; i < instance_fields; ++i) {
- ArtField* f = klass->GetInstanceField(i);
+ for (size_t i = 0; i < klass->NumFields(); ++i) {
+ ArtField* f = klass->GetField(i);
+ if (f->IsStatic()) {
+ continue;
+ }
size_t size;
HprofBasicType t = SignatureToBasicTypeAndSize(f->GetTypeDescriptor(), &size);
switch (t) {
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index 9149f3a6c2..07ab73f38e 100644
--- a/runtime/interpreter/unstarted_runtime.cc
+++ b/runtime/interpreter/unstarted_runtime.cc
@@ -356,20 +356,12 @@ void UnstartedRuntime::UnstartedClassGetDeclaredField(
ObjPtr<mirror::Class> klass = shadow_frame->GetVRegReference(arg_offset)->AsClass();
ObjPtr<mirror::String> name2 = shadow_frame->GetVRegReference(arg_offset + 1)->AsString();
ArtField* found = nullptr;
- for (ArtField& field : klass->GetIFields()) {
+ for (ArtField& field : klass->GetFields()) {
if (name2->Equals(field.GetName())) {
found = &field;
break;
}
}
- if (found == nullptr) {
- for (ArtField& field : klass->GetSFields()) {
- if (name2->Equals(field.GetName())) {
- found = &field;
- break;
- }
- }
- }
if (found != nullptr && ShouldDenyAccessToMember(found, shadow_frame)) {
found = nullptr;
}
diff --git a/runtime/jni/jni_id_manager.cc b/runtime/jni/jni_id_manager.cc
index f295d29640..789265a3e5 100644
--- a/runtime/jni/jni_id_manager.cc
+++ b/runtime/jni/jni_id_manager.cc
@@ -460,19 +460,12 @@ void JniIdManager::VisitReflectiveTargets(ReflectiveValueVisitor* rvv) {
!old_ext_data->HasStaticFieldPointerIdMarker())
<< old_class->PrettyClass();
// Clear the old field mapping.
- if (old_field->IsStatic()) {
- size_t old_off = ArraySlice<ArtField>(old_class->GetSFieldsPtr()).OffsetOf(old_field);
- ObjPtr<mirror::PointerArray> old_statics(old_ext_data->GetStaticJFieldIDsPointerArray());
- if (!old_statics.IsNull()) {
- old_statics->SetElementPtrSize(old_off, 0, kRuntimePointerSize);
- }
- } else {
- size_t old_off = ArraySlice<ArtField>(old_class->GetIFieldsPtr()).OffsetOf(old_field);
- ObjPtr<mirror::PointerArray> old_instances(
- old_ext_data->GetInstanceJFieldIDsPointerArray());
- if (!old_instances.IsNull()) {
- old_instances->SetElementPtrSize(old_off, 0, kRuntimePointerSize);
- }
+ size_t old_off = ArraySlice<ArtField>(old_class->GetFieldsPtr()).OffsetOf(old_field);
+ ObjPtr<mirror::PointerArray> array(old_field->IsStatic()
+ ? old_ext_data->GetStaticJFieldIDsPointerArray()
+ : old_ext_data->GetInstanceJFieldIDsPointerArray());
+ if (!array.IsNull()) {
+ array->SetElementPtrSize(old_off, 0, kRuntimePointerSize);
}
}
if (!new_ext_data.IsNull()) {
@@ -480,19 +473,12 @@ void JniIdManager::VisitReflectiveTargets(ReflectiveValueVisitor* rvv) {
!new_ext_data->HasStaticFieldPointerIdMarker())
<< new_class->PrettyClass();
// Set the new field mapping.
- if (new_field->IsStatic()) {
- size_t new_off = ArraySlice<ArtField>(new_class->GetSFieldsPtr()).OffsetOf(new_field);
- ObjPtr<mirror::PointerArray> new_statics(new_ext_data->GetStaticJFieldIDsPointerArray());
- if (!new_statics.IsNull()) {
- new_statics->SetElementPtrSize(new_off, id, kRuntimePointerSize);
- }
- } else {
- size_t new_off = ArraySlice<ArtField>(new_class->GetIFieldsPtr()).OffsetOf(new_field);
- ObjPtr<mirror::PointerArray> new_instances(
- new_ext_data->GetInstanceJFieldIDsPointerArray());
- if (!new_instances.IsNull()) {
- new_instances->SetElementPtrSize(new_off, id, kRuntimePointerSize);
- }
+ size_t new_off = ArraySlice<ArtField>(new_class->GetFieldsPtr()).OffsetOf(new_field);
+ ObjPtr<mirror::PointerArray> array(new_field->IsStatic()
+ ? new_ext_data->GetStaticJFieldIDsPointerArray()
+ : new_ext_data->GetInstanceJFieldIDsPointerArray());
+ if (!array.IsNull()) {
+ array->SetElementPtrSize(new_off, id, kRuntimePointerSize);
}
}
}
diff --git a/runtime/method_handles.cc b/runtime/method_handles.cc
index 161fa2cd01..7e04d66252 100644
--- a/runtime/method_handles.cc
+++ b/runtime/method_handles.cc
@@ -100,12 +100,12 @@ bool GetUnboxedTypeAndValue(ObjPtr<mirror::Object> o, Primitive::Type* type, JVa
REQUIRES_SHARED(Locks::mutator_lock_) {
ScopedAssertNoThreadSuspension ants(__FUNCTION__);
ObjPtr<mirror::Class> klass = o->GetClass();
- ArtField* primitive_field = &klass->GetIFieldsPtr()->At(0);
-#define CASE_PRIMITIVE(primitive, abbrev, _, shorthand) \
- if (klass == GetBoxedPrimitiveClass(primitive)) { \
- *type = primitive; \
- value->Set ## shorthand(primitive_field->Get ## abbrev(o)); \
- return true; \
+#define CASE_PRIMITIVE(primitive, abbrev, java_name, shorthand) \
+ if (klass == GetBoxedPrimitiveClass(primitive)) { \
+ *type = primitive; \
+ value->Set ## shorthand( \
+ WellKnownClasses::java_lang_ ## java_name ## _value->Get ## abbrev(o)); \
+ return true; \
}
PRIMITIVES_LIST(CASE_PRIMITIVE)
#undef CASE_PRIMITIVE
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 3d3c71759b..82e1462add 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -29,6 +29,7 @@
#include "class_linker.h"
#include "class_loader.h"
#include "common_throws.h"
+#include "dex/class_accessor-inl.h"
#include "dex/dex_file-inl.h"
#include "dex/invoke_type.h"
#include "dex_cache.h"
@@ -643,9 +644,9 @@ inline void Class::SetIfTable(ObjPtr<IfTable> new_iftable) {
IfTableOffset(), new_iftable);
}
-inline LengthPrefixedArray<ArtField>* Class::GetIFieldsPtr() {
+inline LengthPrefixedArray<ArtField>* Class::GetFieldsPtr() {
DCHECK(IsLoaded() || IsErroneous()) << GetStatus();
- return GetFieldPtr<LengthPrefixedArray<ArtField>*>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_));
+ return GetFieldPtr<LengthPrefixedArray<ArtField>*>(OFFSET_OF_OBJECT_MEMBER(Class, fields_));
}
template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
@@ -680,44 +681,21 @@ inline MemberOffset Class::GetFirstReferenceStaticFieldOffsetDuringLinking(
return MemberOffset(base);
}
-inline void Class::SetIFieldsPtr(LengthPrefixedArray<ArtField>* new_ifields) {
- DCHECK(GetIFieldsPtrUnchecked() == nullptr);
- return SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), new_ifields);
+inline void Class::SetFieldsPtr(LengthPrefixedArray<ArtField>* new_fields) {
+ DCHECK(GetFieldsPtrUnchecked() == nullptr);
+ return SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(Class, fields_), new_fields);
}
-inline void Class::SetIFieldsPtrUnchecked(LengthPrefixedArray<ArtField>* new_ifields) {
- SetFieldPtr<false, true, kVerifyNone>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), new_ifields);
+inline void Class::SetFieldsPtrUnchecked(LengthPrefixedArray<ArtField>* new_fields) {
+ SetFieldPtr<false, true, kVerifyNone>(OFFSET_OF_OBJECT_MEMBER(Class, fields_), new_fields);
}
-inline LengthPrefixedArray<ArtField>* Class::GetSFieldsPtrUnchecked() {
- return GetFieldPtr<LengthPrefixedArray<ArtField>*>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_));
+inline LengthPrefixedArray<ArtField>* Class::GetFieldsPtrUnchecked() {
+ return GetFieldPtr<LengthPrefixedArray<ArtField>*>(OFFSET_OF_OBJECT_MEMBER(Class, fields_));
}
-inline LengthPrefixedArray<ArtField>* Class::GetIFieldsPtrUnchecked() {
- return GetFieldPtr<LengthPrefixedArray<ArtField>*>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_));
-}
-
-inline LengthPrefixedArray<ArtField>* Class::GetSFieldsPtr() {
- DCHECK(IsLoaded() || IsErroneous()) << GetStatus();
- return GetSFieldsPtrUnchecked();
-}
-
-inline void Class::SetSFieldsPtr(LengthPrefixedArray<ArtField>* new_sfields) {
- DCHECK((IsRetired() && new_sfields == nullptr) ||
- GetFieldPtr<ArtField*>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_)) == nullptr);
- SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), new_sfields);
-}
-
-inline void Class::SetSFieldsPtrUnchecked(LengthPrefixedArray<ArtField>* new_sfields) {
- SetFieldPtr<false, true, kVerifyNone>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), new_sfields);
-}
-
-inline ArtField* Class::GetStaticField(uint32_t i) {
- return &GetSFieldsPtr()->At(i);
-}
-
-inline ArtField* Class::GetInstanceField(uint32_t i) {
- return &GetIFieldsPtr()->At(i);
+inline ArtField* Class::GetField(uint32_t i) {
+ return &GetFieldsPtr()->At(i);
}
template<VerifyObjectFlags kVerifyFlags>
@@ -1020,8 +998,8 @@ inline void Class::AssertInitializedOrInitializingInThread(Thread* self) {
inline ObjPtr<ObjectArray<Class>> Class::GetProxyInterfaces() {
CHECK(IsProxyClass());
- // First static field.
- ArtField* field = GetStaticField(0);
+ // First field.
+ ArtField* field = GetField(0);
DCHECK_STREQ(field->GetName(), "interfaces");
MemberOffset field_offset = field->GetOffset();
return GetFieldObject<ObjectArray<Class>>(field_offset);
@@ -1029,8 +1007,8 @@ inline ObjPtr<ObjectArray<Class>> Class::GetProxyInterfaces() {
inline ObjPtr<ObjectArray<ObjectArray<Class>>> Class::GetProxyThrows() {
CHECK(IsProxyClass());
- // Second static field.
- ArtField* field = GetStaticField(1);
+ // Second field.
+ ArtField* field = GetField(1);
DCHECK_STREQ(field->GetName(), "throws");
MemberOffset field_offset = field->GetOffset();
return GetFieldObject<ObjectArray<ObjectArray<Class>>>(field_offset);
@@ -1124,20 +1102,12 @@ inline ArraySlice<ArtMethod> Class::GetMethods(PointerSize pointer_size) {
return GetMethodsSliceRangeUnchecked(methods, pointer_size, 0u, NumMethods(methods));
}
-inline IterationRange<StrideIterator<ArtField>> Class::GetIFields() {
- return MakeIterationRangeFromLengthPrefixedArray(GetIFieldsPtr());
+inline IterationRange<StrideIterator<ArtField>> Class::GetFields() {
+ return MakeIterationRangeFromLengthPrefixedArray(GetFieldsPtr());
}
-inline IterationRange<StrideIterator<ArtField>> Class::GetSFields() {
- return MakeIterationRangeFromLengthPrefixedArray(GetSFieldsPtr());
-}
-
-inline IterationRange<StrideIterator<ArtField>> Class::GetIFieldsUnchecked() {
- return MakeIterationRangeFromLengthPrefixedArray(GetIFieldsPtrUnchecked());
-}
-
-inline IterationRange<StrideIterator<ArtField>> Class::GetSFieldsUnchecked() {
- return MakeIterationRangeFromLengthPrefixedArray(GetSFieldsPtrUnchecked());
+inline IterationRange<StrideIterator<ArtField>> Class::GetFieldsUnchecked() {
+ return MakeIterationRangeFromLengthPrefixedArray(GetFieldsPtrUnchecked());
}
inline void Class::CheckPointerSize(PointerSize pointer_size) {
@@ -1234,14 +1204,37 @@ inline uint32_t Class::NumVirtualMethods() {
return NumMethods() - GetVirtualMethodsStartOffset();
}
-inline uint32_t Class::NumInstanceFields() {
- LengthPrefixedArray<ArtField>* arr = GetIFieldsPtrUnchecked();
+inline uint32_t Class::NumFields() {
+ LengthPrefixedArray<ArtField>* arr = GetFieldsPtrUnchecked();
return arr != nullptr ? arr->size() : 0u;
}
-inline uint32_t Class::NumStaticFields() {
- LengthPrefixedArray<ArtField>* arr = GetSFieldsPtrUnchecked();
- return arr != nullptr ? arr->size() : 0u;
+inline bool Class::HasStaticFields() {
+ if (IsArrayClass() || IsPrimitive()) {
+ return false;
+ }
+ ClassAccessor accessor(GetDexFile(), GetDexClassDefIndex());
+ return accessor.NumStaticFields() != 0u;
+}
+
+inline uint32_t Class::ComputeNumStaticFields() {
+ uint32_t num = 0;
+ for (ArtField& field : GetFields()) {
+ if (field.IsStatic()) {
+ ++num;
+ }
+ }
+ return num;
+}
+
+inline uint32_t Class::ComputeNumInstanceFields() {
+ uint32_t num = 0;
+ for (ArtField& field : GetFields()) {
+ if (!field.IsStatic()) {
+ ++num;
+ }
+ }
+ return num;
}
template <typename T, VerifyObjectFlags kVerifyFlags, typename Visitor>
@@ -1262,11 +1255,9 @@ template <VerifyObjectFlags kVerifyFlags, typename Visitor>
inline void Class::FixupNativePointers(Class* dest,
PointerSize pointer_size,
const Visitor& visitor) {
- // Update the field arrays.
- FixupNativePointer<LengthPrefixedArray<ArtField>*, kVerifyFlags>(
- dest, pointer_size, visitor, OFFSET_OF_OBJECT_MEMBER(Class, sfields_));
+ // Update the field array.
FixupNativePointer<LengthPrefixedArray<ArtField>*, kVerifyFlags>(
- dest, pointer_size, visitor, OFFSET_OF_OBJECT_MEMBER(Class, ifields_));
+ dest, pointer_size, visitor, OFFSET_OF_OBJECT_MEMBER(Class, fields_));
// Update method array.
FixupNativePointer<LengthPrefixedArray<ArtMethod>*, kVerifyFlags>(
dest, pointer_size, visitor, OFFSET_OF_OBJECT_MEMBER(Class, methods_));
diff --git a/runtime/mirror/class-refvisitor-inl.h b/runtime/mirror/class-refvisitor-inl.h
index 96c218b175..8de27de485 100644
--- a/runtime/mirror/class-refvisitor-inl.h
+++ b/runtime/mirror/class-refvisitor-inl.h
@@ -120,11 +120,8 @@ void Class::VisitMethods(Visitor visitor, PointerSize pointer_size) {
template<ReadBarrierOption kReadBarrierOption, class Visitor>
void Class::VisitFields(Visitor visitor) {
- for (ArtField& sfield : GetSFieldsUnchecked()) {
- visitor(&sfield);
- }
- for (ArtField& ifield : GetIFieldsUnchecked()) {
- visitor(&ifield);
+ for (ArtField& field : GetFieldsUnchecked()) {
+ visitor(&field);
}
}
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;
}
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 9560f985ac..9a45a73e72 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -1032,21 +1032,24 @@ class EXPORT MANAGED Class final : public Object {
ALWAYS_INLINE void SetIfTable(ObjPtr<IfTable> new_iftable)
REQUIRES_SHARED(Locks::mutator_lock_);
- // Get instance fields of the class (See also GetSFields).
- LengthPrefixedArray<ArtField>* GetIFieldsPtr() REQUIRES_SHARED(Locks::mutator_lock_);
+ // Get fields of the class.
+ LengthPrefixedArray<ArtField>* GetFieldsPtr() REQUIRES_SHARED(Locks::mutator_lock_);
- ALWAYS_INLINE IterationRange<StrideIterator<ArtField>> GetIFields()
+ ALWAYS_INLINE IterationRange<StrideIterator<ArtField>> GetFields()
REQUIRES_SHARED(Locks::mutator_lock_);
- void SetIFieldsPtr(LengthPrefixedArray<ArtField>* new_ifields)
+ void SetFieldsPtr(LengthPrefixedArray<ArtField>* new_fields)
REQUIRES_SHARED(Locks::mutator_lock_);
// Unchecked edition has no verification flags.
- void SetIFieldsPtrUnchecked(LengthPrefixedArray<ArtField>* new_sfields)
+ void SetFieldsPtrUnchecked(LengthPrefixedArray<ArtField>* new_fields)
REQUIRES_SHARED(Locks::mutator_lock_);
- uint32_t NumInstanceFields() REQUIRES_SHARED(Locks::mutator_lock_);
- ArtField* GetInstanceField(uint32_t i) REQUIRES_SHARED(Locks::mutator_lock_);
+ ArtField* GetField(uint32_t i) REQUIRES_SHARED(Locks::mutator_lock_);
+ uint32_t NumFields() REQUIRES_SHARED(Locks::mutator_lock_);
+ bool HasStaticFields() REQUIRES_SHARED(Locks::mutator_lock_);
+ uint32_t ComputeNumStaticFields() REQUIRES_SHARED(Locks::mutator_lock_);
+ uint32_t ComputeNumInstanceFields() REQUIRES_SHARED(Locks::mutator_lock_);
// Returns the number of instance fields containing reference types. Does not count fields in any
// super classes.
@@ -1104,23 +1107,6 @@ class EXPORT MANAGED Class final : public Object {
MemberOffset GetFirstReferenceStaticFieldOffsetDuringLinking(PointerSize pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_);
- // Gets the static fields of the class.
- LengthPrefixedArray<ArtField>* GetSFieldsPtr() REQUIRES_SHARED(Locks::mutator_lock_);
- ALWAYS_INLINE IterationRange<StrideIterator<ArtField>> GetSFields()
- REQUIRES_SHARED(Locks::mutator_lock_);
-
- void SetSFieldsPtr(LengthPrefixedArray<ArtField>* new_sfields)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
- // Unchecked edition has no verification flags.
- void SetSFieldsPtrUnchecked(LengthPrefixedArray<ArtField>* new_sfields)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
- uint32_t NumStaticFields() REQUIRES_SHARED(Locks::mutator_lock_);
-
- // TODO: uint16_t
- ArtField* GetStaticField(uint32_t i) REQUIRES_SHARED(Locks::mutator_lock_);
-
// Find a static or instance field using the JLS resolution order
ArtField* FindField(ObjPtr<mirror::DexCache> dex_cache, uint32_t field_idx)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -1134,6 +1120,12 @@ class EXPORT MANAGED Class final : public Object {
ArtField* FindInstanceField(ObjPtr<DexCache> dex_cache, uint32_t dex_field_idx)
REQUIRES_SHARED(Locks::mutator_lock_);
+ ArtField* FindDeclaredField(ObjPtr<DexCache> dex_cache, uint32_t dex_field_idx)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
+ ArtField* FindDeclaredField(std::string_view name, std::string_view type)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
ArtField* FindDeclaredInstanceField(std::string_view name, std::string_view type)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -1384,7 +1376,7 @@ class EXPORT MANAGED Class final : public Object {
REQUIRES_SHARED(Locks::mutator_lock_);
ObjPtr<Object> GetInstanceFieldIds() REQUIRES_SHARED(Locks::mutator_lock_);
- // Calculate the index in the ifields_, methods_ or sfields_ arrays a method is located at. This
+ // Calculate the index in the fields_ or methods_ arrays a method is located at. This
// is to be used with the above Get{,OrCreate}...Ids functions.
size_t GetStaticFieldIdOffset(ArtField* field)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -1426,11 +1418,8 @@ class EXPORT MANAGED Class final : public Object {
void CheckObjectAlloc() REQUIRES_SHARED(Locks::mutator_lock_);
// Unchecked editions is for root visiting.
- LengthPrefixedArray<ArtField>* GetSFieldsPtrUnchecked() REQUIRES_SHARED(Locks::mutator_lock_);
- IterationRange<StrideIterator<ArtField>> GetSFieldsUnchecked()
- REQUIRES_SHARED(Locks::mutator_lock_);
- LengthPrefixedArray<ArtField>* GetIFieldsPtrUnchecked() REQUIRES_SHARED(Locks::mutator_lock_);
- IterationRange<StrideIterator<ArtField>> GetIFieldsUnchecked()
+ LengthPrefixedArray<ArtField>* GetFieldsPtrUnchecked() REQUIRES_SHARED(Locks::mutator_lock_);
+ IterationRange<StrideIterator<ArtField>> GetFieldsUnchecked()
REQUIRES_SHARED(Locks::mutator_lock_);
// The index in the methods_ array where the first declared virtual method is.
@@ -1514,16 +1503,16 @@ class EXPORT MANAGED Class final : public Object {
// virtual_ methods_ for miranda methods.
HeapReference<PointerArray> vtable_;
- // instance fields
+ // instance and static fields
//
// These describe the layout of the contents of an Object.
// Note that only the fields directly declared by this class are
- // listed in ifields; fields declared by a superclass are listed in
- // the superclass's Class.ifields.
+ // listed in `fields_`; fields declared by a superclass are listed in
+ // the superclass's `Class.fields_`.
//
// ArtFields are allocated as a length prefixed ArtField array, and not an array of pointers to
// ArtFields.
- uint64_t ifields_;
+ uint64_t fields_;
// Pointer to an ArtMethod length-prefixed array. All the methods where this class is the place
// where they are logically defined. This includes all private, static, final and virtual methods
@@ -1542,9 +1531,6 @@ class EXPORT MANAGED Class final : public Object {
// Note that this field is used by the native debugger as the unique identifier for the type.
uint64_t methods_;
- // Static fields length-prefixed array.
- uint64_t sfields_;
-
// Access flags; low 16 bits are defined by VM spec.
uint32_t access_flags_;
@@ -1587,7 +1573,7 @@ class EXPORT MANAGED Class final : public Object {
// bits contains the size shift of the primitive type.
uint32_t primitive_type_;
- // Bitmap of offsets of ifields.
+ // Bitmap of offsets of instance fields.
uint32_t reference_instance_offsets_;
// See the real definition in subtype_check_bits_and_status.h
@@ -1611,7 +1597,7 @@ class EXPORT MANAGED Class final : public Object {
// VTableEntry embedded_vtable_[0];
// Static fields, variable size.
// uint32_t fields_[0];
- // Embedded bitmap of offsets of ifields, for classes that need more than 31
+ // Embedded bitmap of offsets of instance fields, for classes that need more than 31
// reference-offset bits. 'reference_instance_offsets_' stores the number of
// 32-bit entries that hold the entire bitmap. We compute the offset of first
// entry by subtracting this number from class_size_.
diff --git a/runtime/mirror/dex_cache.cc b/runtime/mirror/dex_cache.cc
index b981f08d97..7dc407c737 100644
--- a/runtime/mirror/dex_cache.cc
+++ b/runtime/mirror/dex_cache.cc
@@ -245,10 +245,7 @@ void DexCache::SetResolvedType(dex::TypeIndex type_idx, ObjPtr<Class> resolved)
}
auto* resolved_fields = GetResolvedFieldsArray();
if (resolved_fields != nullptr) {
- for (ArtField& current_field : resolved->GetSFields()) {
- resolved_fields->Set(current_field.GetDexFieldIndex(), &current_field);
- }
- for (ArtField& current_field : resolved->GetIFields()) {
+ for (ArtField& current_field : resolved->GetFields()) {
resolved_fields->Set(current_field.GetDexFieldIndex(), &current_field);
}
}
diff --git a/runtime/mirror/dex_cache_test.cc b/runtime/mirror/dex_cache_test.cc
index 1429bb3e04..f2cfcbf050 100644
--- a/runtime/mirror/dex_cache_test.cc
+++ b/runtime/mirror/dex_cache_test.cc
@@ -85,14 +85,16 @@ TEST_F(DexCacheTest, TestResolvedFieldAccess) {
ASSERT_TRUE(klass2 != nullptr);
EXPECT_OBJ_PTR_EQ(klass1->GetDexCache(), klass2->GetDexCache());
- EXPECT_NE(klass1->NumStaticFields(), 0u);
- for (ArtField& field : klass2->GetSFields()) {
- EXPECT_FALSE(
- klass1->ResolvedFieldAccessTest</*throw_on_failure=*/ false>(
- klass2.Get(),
- &field,
- klass1->GetDexCache(),
- field.GetDexFieldIndex()));
+ EXPECT_NE(klass1->ComputeNumStaticFields(), 0u);
+ for (ArtField& field : klass2->GetFields()) {
+ if (field.IsStatic()) {
+ EXPECT_FALSE(
+ klass1->ResolvedFieldAccessTest</*throw_on_failure=*/ false>(
+ klass2.Get(),
+ &field,
+ klass1->GetDexCache(),
+ field.GetDexFieldIndex()));
+ }
}
}
diff --git a/runtime/mirror/field.cc b/runtime/mirror/field.cc
index 5ad59fadf4..40af891f01 100644
--- a/runtime/mirror/field.cc
+++ b/runtime/mirror/field.cc
@@ -32,8 +32,7 @@ void Field::VisitTarget(ReflectiveValueVisitor* v) {
if (orig != new_value) {
SetOffset<false>(new_value->GetOffset().Int32Value());
SetDeclaringClass<false>(new_value->GetDeclaringClass());
- auto new_range =
- IsStatic() ? GetDeclaringClass()->GetSFields() : GetDeclaringClass()->GetIFields();
+ auto new_range = GetDeclaringClass()->GetFields();
auto position = std::find_if(
new_range.begin(), new_range.end(), [&](const auto& f) { return &f == new_value; });
DCHECK(position != new_range.end());
@@ -45,13 +44,7 @@ void Field::VisitTarget(ReflectiveValueVisitor* v) {
ArtField* Field::GetArtField() {
ObjPtr<mirror::Class> declaring_class = GetDeclaringClass();
- if (IsStatic()) {
- DCHECK_LT(GetArtFieldIndex(), declaring_class->NumStaticFields());
- return declaring_class->GetStaticField(GetArtFieldIndex());
- } else {
- DCHECK_LT(GetArtFieldIndex(), declaring_class->NumInstanceFields());
- return declaring_class->GetInstanceField(GetArtFieldIndex());
- }
+ return declaring_class->GetField(GetArtFieldIndex());
}
ObjPtr<mirror::Field> Field::CreateFromArtField(Thread* self,
@@ -86,8 +79,7 @@ ObjPtr<mirror::Field> Field::CreateFromArtField(Thread* self,
field->GetDeclaringClass());
ret->SetAccessFlags</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
field->GetAccessFlags());
- auto iter_range = field->IsStatic() ? field->GetDeclaringClass()->GetSFields()
- : field->GetDeclaringClass()->GetIFields();
+ auto iter_range = field->GetDeclaringClass()->GetFields();
auto position = std::find_if(
iter_range.begin(), iter_range.end(), [&](const auto& f) { return &f == field; });
DCHECK(position != iter_range.end());
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index b28978603c..3fa71c66d1 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -248,8 +248,8 @@ void Object::CheckFieldAssignmentImpl(MemberOffset field_offset, ObjPtr<Object>
return;
}
for (ObjPtr<Class> cur = c; cur != nullptr; cur = cur->GetSuperClass()) {
- for (ArtField& field : cur->GetIFields()) {
- if (field.GetOffset().Int32Value() == field_offset.Int32Value()) {
+ for (ArtField& field : cur->GetFields()) {
+ if (!field.IsStatic() && field.GetOffset().Int32Value() == field_offset.Int32Value()) {
CHECK_NE(field.GetTypeAsPrimitiveType(), Primitive::kPrimNot);
// TODO: resolve the field type for moving GC.
ObjPtr<mirror::Class> field_type =
@@ -266,8 +266,8 @@ void Object::CheckFieldAssignmentImpl(MemberOffset field_offset, ObjPtr<Object>
return;
}
if (IsClass()) {
- for (ArtField& field : AsClass()->GetSFields()) {
- if (field.GetOffset().Int32Value() == field_offset.Int32Value()) {
+ for (ArtField& field : AsClass()->GetFields()) {
+ if (field.IsStatic() && field.GetOffset().Int32Value() == field_offset.Int32Value()) {
CHECK_NE(field.GetTypeAsPrimitiveType(), Primitive::kPrimNot);
// TODO: resolve the field type for moving GC.
ObjPtr<mirror::Class> field_type =
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index c31c9790bd..09bd9abec7 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -290,11 +290,7 @@ ALWAYS_INLINE static inline ObjPtr<mirror::Field> GetDeclaredField(Thread* self,
ThrowRuntimeException("Obsolete Object!");
return nullptr;
}
- ArtField* art_field = FindFieldByName(name, c->GetIFieldsPtr());
- if (art_field != nullptr) {
- return mirror::Field::CreateFromArtField(self, art_field, true);
- }
- art_field = FindFieldByName(name, c->GetSFieldsPtr());
+ ArtField* art_field = FindFieldByName(name, c->GetFieldsPtr());
if (art_field != nullptr) {
return mirror::Field::CreateFromArtField(self, art_field, true);
}
diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc
index f9bf31bedd..d0e40d86bb 100644
--- a/runtime/proxy_test.cc
+++ b/runtime/proxy_test.cc
@@ -93,11 +93,10 @@ TEST_F(ProxyTest, ProxyFieldHelper) {
ASSERT_TRUE(proxyClass->IsProxyClass());
ASSERT_TRUE(proxyClass->IsInitialized());
- EXPECT_TRUE(proxyClass->GetIFieldsPtr() == nullptr);
-
- LengthPrefixedArray<ArtField>* static_fields = proxyClass->GetSFieldsPtr();
- ASSERT_TRUE(static_fields != nullptr);
- ASSERT_EQ(2u, proxyClass->NumStaticFields());
+ LengthPrefixedArray<ArtField>* fields = proxyClass->GetFieldsPtr();
+ ASSERT_TRUE(fields != nullptr);
+ ASSERT_EQ(2u, proxyClass->NumFields());
+ ASSERT_EQ(0u, proxyClass->ComputeNumInstanceFields());
Handle<mirror::Class> interfacesFieldClass(
hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/Class;")));
@@ -107,7 +106,7 @@ TEST_F(ProxyTest, ProxyFieldHelper) {
ASSERT_TRUE(throwsFieldClass != nullptr);
// Test "Class[] interfaces" field.
- ArtField* field = &static_fields->At(0);
+ ArtField* field = &fields->At(0);
EXPECT_STREQ("interfaces", field->GetName());
EXPECT_STREQ("[Ljava/lang/Class;", field->GetTypeDescriptor());
EXPECT_EQ("[Ljava/lang/Class;", field->GetTypeDescriptorView());
@@ -117,7 +116,7 @@ TEST_F(ProxyTest, ProxyFieldHelper) {
EXPECT_FALSE(field->IsPrimitiveType());
// Test "Class[][] throws" field.
- field = &static_fields->At(1);
+ field = &fields->At(1);
EXPECT_STREQ("throws", field->GetName());
EXPECT_STREQ("[[Ljava/lang/Class;", field->GetTypeDescriptor());
EXPECT_EQ("[[Ljava/lang/Class;", field->GetTypeDescriptorView());
@@ -149,10 +148,10 @@ TEST_F(ProxyTest, CheckArtMirrorFieldsOfProxyStaticFields) {
ASSERT_TRUE(proxyClass1->IsProxyClass());
ASSERT_TRUE(proxyClass1->IsInitialized());
- LengthPrefixedArray<ArtField>* static_fields0 = proxyClass0->GetSFieldsPtr();
+ LengthPrefixedArray<ArtField>* static_fields0 = proxyClass0->GetFieldsPtr();
ASSERT_TRUE(static_fields0 != nullptr);
ASSERT_EQ(2u, static_fields0->size());
- LengthPrefixedArray<ArtField>* static_fields1 = proxyClass1->GetSFieldsPtr();
+ LengthPrefixedArray<ArtField>* static_fields1 = proxyClass1->GetFieldsPtr();
ASSERT_TRUE(static_fields1 != nullptr);
ASSERT_EQ(2u, static_fields1->size());
diff --git a/runtime/runtime_image.cc b/runtime/runtime_image.cc
index c73810de59..7bfefe5278 100644
--- a/runtime/runtime_image.cc
+++ b/runtime/runtime_image.cc
@@ -860,27 +860,23 @@ class RuntimeImageHelper {
void CopyFieldArrays(ObjPtr<mirror::Class> cls, uint32_t class_image_address)
REQUIRES_SHARED(Locks::mutator_lock_) {
- LengthPrefixedArray<ArtField>* fields[] = {
- cls->GetSFieldsPtr(), cls->GetIFieldsPtr(),
- };
- for (LengthPrefixedArray<ArtField>* cur_fields : fields) {
- if (cur_fields != nullptr) {
- // Copy the array.
- size_t number_of_fields = cur_fields->size();
- size_t size = LengthPrefixedArray<ArtField>::ComputeSize(number_of_fields);
- size_t offset = art_fields_.size();
- art_fields_.resize(offset + size);
- auto* dest_array =
- reinterpret_cast<LengthPrefixedArray<ArtField>*>(art_fields_.data() + offset);
- memcpy(dest_array, cur_fields, size);
- native_relocations_.Put(cur_fields,
- std::make_pair(NativeRelocationKind::kArtFieldArray, offset));
-
- // Update the class pointer of individual fields.
- for (size_t i = 0; i != number_of_fields; ++i) {
- dest_array->At(i).GetDeclaringClassAddressWithoutBarrier()->Assign(
- reinterpret_cast<mirror::Class*>(class_image_address));
- }
+ LengthPrefixedArray<ArtField>* cur_fields = cls->GetFieldsPtr();
+ if (cur_fields != nullptr) {
+ // Copy the array.
+ size_t number_of_fields = cur_fields->size();
+ size_t size = LengthPrefixedArray<ArtField>::ComputeSize(number_of_fields);
+ size_t offset = art_fields_.size();
+ art_fields_.resize(offset + size);
+ auto* dest_array =
+ reinterpret_cast<LengthPrefixedArray<ArtField>*>(art_fields_.data() + offset);
+ memcpy(dest_array, cur_fields, size);
+ native_relocations_.Put(cur_fields,
+ std::make_pair(NativeRelocationKind::kArtFieldArray, offset));
+
+ // Update the class pointer of individual fields.
+ for (size_t i = 0; i != number_of_fields; ++i) {
+ dest_array->At(i).GetDeclaringClassAddressWithoutBarrier()->Assign(
+ reinterpret_cast<mirror::Class*>(class_image_address));
}
}
}
@@ -1429,7 +1425,7 @@ class RuntimeImageHelper {
}
// Trivial case: no static fields.
- if (cls->NumStaticFields() == 0u) {
+ if (!cls->HasStaticFields()) {
return true;
}
diff --git a/test/906-iterate-heap/expected-stdout.txt b/test/906-iterate-heap/expected-stdout.txt
index 73b7129bba..125e65132e 100644
--- a/test/906-iterate-heap/expected-stdout.txt
+++ b/test/906-iterate-heap/expected-stdout.txt
@@ -19,27 +19,27 @@
1@0 (32, 2xD '0000000000000000000000000000f03f')
2
doTestPrimitiveFieldsClasses
-10000@0 (static, int, index=3) 0000000000000000
+10000@0 (static, int, index=9) 0000000000000000
10001
-10000@0 (static, int, index=11) 0000000000000000
+10000@0 (static, int, index=14) 0000000000000000
10001
10001
10001
doTestPrimitiveFieldsIntegral
10000@0 (instance, int, index=2) 0000000000000000
+10001@0 (instance, byte, index=3) 0000000000000001
+10002@0 (instance, char, index=4) 0000000000000061
+10003@0 (instance, int, index=5) 0000000000000003
+10004@0 (instance, long, index=6) 0000000000000004
+10005@0 (instance, short, index=8) 0000000000000002
+10006
+doTestPrimitiveFieldsFloat
+10000@0 (instance, int, index=3) 0000000000000000
10001@0 (instance, byte, index=4) 0000000000000001
10002@0 (instance, char, index=5) 0000000000000061
10003@0 (instance, int, index=6) 0000000000000003
10004@0 (instance, long, index=7) 0000000000000004
10005@0 (instance, short, index=9) 0000000000000002
-10006
-doTestPrimitiveFieldsFloat
-10000@0 (instance, int, index=3) 0000000000000000
-10001@0 (instance, byte, index=5) 0000000000000001
-10002@0 (instance, char, index=6) 0000000000000061
-10003@0 (instance, int, index=7) 0000000000000003
-10004@0 (instance, long, index=8) 0000000000000004
-10005@0 (instance, short, index=10) 0000000000000002
-10006@0 (instance, double, index=12) 3ff3ae147ae147ae
-10007@0 (instance, float, index=13) 000000003f9d70a4
+10006@0 (instance, double, index=11) 3ff3ae147ae147ae
+10007@0 (instance, float, index=12) 000000003f9d70a4
10008
diff --git a/test/913-heaps/expected-stdout.txt b/test/913-heaps/expected-stdout.txt
index 7d3622305a..87ad2d669d 100644
--- a/test/913-heaps/expected-stdout.txt
+++ b/test/913-heaps/expected-stdout.txt
@@ -128,27 +128,27 @@ root@root --(thread)--> 3000@0 [size=120, length=-1]
4@0 (18, 3xS '010002000300')
1@0 (14, 2xZ '0001')
23456789
-10000@0 (static, int, index=3) 0000000000000000
+10000@0 (static, int, index=9) 0000000000000000
10001
-10000@0 (static, int, index=11) 0000000000000000
+10000@0 (static, int, index=14) 0000000000000000
10001
10001
10001
10000@0 (instance, int, index=2) 0000000000000000
+10001@0 (instance, byte, index=3) 0000000000000001
+10002@0 (instance, char, index=4) 0000000000000061
+10003@0 (instance, int, index=5) 0000000000000003
+10004@0 (instance, long, index=6) 0000000000000004
+10005@0 (instance, short, index=8) 0000000000000002
+10006
+10000@0 (instance, int, index=3) 0000000000000000
10001@0 (instance, byte, index=4) 0000000000000001
10002@0 (instance, char, index=5) 0000000000000061
10003@0 (instance, int, index=6) 0000000000000003
10004@0 (instance, long, index=7) 0000000000000004
10005@0 (instance, short, index=9) 0000000000000002
-10006
-10000@0 (instance, int, index=3) 0000000000000000
-10001@0 (instance, byte, index=5) 0000000000000001
-10002@0 (instance, char, index=6) 0000000000000061
-10003@0 (instance, int, index=7) 0000000000000003
-10004@0 (instance, long, index=8) 0000000000000004
-10005@0 (instance, short, index=10) 0000000000000002
-10006@0 (instance, double, index=12) 3ff3ae147ae147ae
-10007@0 (instance, float, index=13) 000000003f9d70a4
+10006@0 (instance, double, index=11) 3ff3ae147ae147ae
+10007@0 (instance, float, index=12) 000000003f9d70a4
10008
--- klass ---
root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=0,location= 31])--> 1@1000 [size=16, length=-1]