Keep original order of fields in Class.
The fields of a class are ordered alphabetically in the dex
file. Keep the same order in the field arrays so that we can
do binary search lookups by name. Those lookups will be
implemented in a subsequent change in libcore/.
Bug: 18211592
(cherry picked from commit bfa3ed0ad988e1da13626ddbaf6dcae0c58ea79e)
Change-Id: I8f979de62ffe37d1c7d5c721717d2f3501e7c9e6
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 5f72dbe..a69d37e 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -402,6 +402,36 @@
return GetFieldObject<ObjectArray<ArtField>>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_));
}
+inline MemberOffset Class::GetFirstReferenceInstanceFieldOffset() {
+ Class* super_class = GetSuperClass();
+ return (super_class != nullptr)
+ ? MemberOffset(RoundUp(super_class->GetObjectSize(),
+ sizeof(mirror::HeapReference<mirror::Object>)))
+ : ClassOffset();
+}
+
+inline MemberOffset Class::GetFirstReferenceStaticFieldOffset() {
+ DCHECK(IsResolved());
+ uint32_t base = sizeof(mirror::Class); // Static fields come after the class.
+ if (ShouldHaveEmbeddedImtAndVTable()) {
+ // Static fields come after the embedded tables.
+ base = mirror::Class::ComputeClassSize(true, GetEmbeddedVTableLength(),
+ 0, 0, 0, 0, 0);
+ }
+ return MemberOffset(base);
+}
+
+inline MemberOffset Class::GetFirstReferenceStaticFieldOffsetDuringLinking() {
+ DCHECK(IsLoaded());
+ uint32_t base = sizeof(mirror::Class); // Static fields come after the class.
+ if (ShouldHaveEmbeddedImtAndVTable()) {
+ // Static fields come after the embedded tables.
+ base = mirror::Class::ComputeClassSize(true, GetVTableDuringLinking()->GetLength(),
+ 0, 0, 0, 0, 0);
+ }
+ return MemberOffset(base);
+}
+
inline void Class::SetIFields(ObjectArray<ArtField>* new_ifields)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(NULL == GetFieldObject<ObjectArray<ArtField>>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_)));
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 4f1af44..f45ea85 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -837,6 +837,9 @@
void SetReferenceInstanceOffsets(uint32_t new_reference_offsets)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ // Get the offset of the first reference instance field. Other reference instance fields follow.
+ MemberOffset GetFirstReferenceInstanceFieldOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
// Returns the number of static fields containing reference types.
uint32_t NumReferenceStaticFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(IsResolved() || IsErroneous());
@@ -853,6 +856,13 @@
SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_static_fields_), new_num);
}
+ // Get the offset of the first reference static field. Other reference static fields follow.
+ MemberOffset GetFirstReferenceStaticFieldOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ // Get the offset of the first reference static field. Other reference static fields follow.
+ MemberOffset GetFirstReferenceStaticFieldOffsetDuringLinking()
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
// Gets the static fields of the class.
ObjectArray<ArtField>* GetSFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index c451764..4199eef 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -911,13 +911,19 @@
klass = kIsStatic ? nullptr : klass->GetSuperClass()) {
size_t num_reference_fields =
kIsStatic ? klass->NumReferenceStaticFields() : klass->NumReferenceInstanceFields();
+ if (num_reference_fields == 0u) {
+ continue;
+ }
+ MemberOffset field_offset = kIsStatic
+ ? klass->GetFirstReferenceStaticFieldOffset()
+ : klass->GetFirstReferenceInstanceFieldOffset();
for (size_t i = 0; i < num_reference_fields; ++i) {
- mirror::ArtField* field = kIsStatic ? klass->GetStaticField(i) : klass->GetInstanceField(i);
- MemberOffset field_offset = field->GetOffset();
// TODO: Do a simpler check?
if (kVisitClass || field_offset.Uint32Value() != ClassOffset().Uint32Value()) {
visitor(this, field_offset, kIsStatic);
}
+ field_offset = MemberOffset(field_offset.Uint32Value() +
+ sizeof(mirror::HeapReference<mirror::Object>));
}
}
}
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index 4227723..fa1f226 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -200,10 +200,11 @@
for (Class* cur = c; cur != NULL; cur = cur->GetSuperClass()) {
ObjectArray<ArtField>* fields = cur->GetIFields();
if (fields != NULL) {
- size_t num_ref_ifields = cur->NumReferenceInstanceFields();
- for (size_t i = 0; i < num_ref_ifields; ++i) {
+ size_t num_ifields = fields->GetLength();
+ for (size_t i = 0; i < num_ifields; ++i) {
ArtField* field = fields->Get(i);
if (field->GetOffset().Int32Value() == field_offset.Int32Value()) {
+ CHECK_NE(field->GetTypeAsPrimitiveType(), Primitive::kPrimNot);
StackHandleScope<1> hs(Thread::Current());
FieldHelper fh(hs.NewHandle(field));
CHECK(fh.GetType()->IsAssignableFrom(new_value->GetClass()));
@@ -219,10 +220,11 @@
if (IsClass()) {
ObjectArray<ArtField>* fields = AsClass()->GetSFields();
if (fields != NULL) {
- size_t num_ref_sfields = AsClass()->NumReferenceStaticFields();
- for (size_t i = 0; i < num_ref_sfields; ++i) {
+ size_t num_sfields = fields->GetLength();
+ for (size_t i = 0; i < num_sfields; ++i) {
ArtField* field = fields->Get(i);
if (field->GetOffset().Int32Value() == field_offset.Int32Value()) {
+ CHECK_NE(field->GetTypeAsPrimitiveType(), Primitive::kPrimNot);
StackHandleScope<1> hs(Thread::Current());
FieldHelper fh(hs.NewHandle(field));
CHECK(fh.GetType()->IsAssignableFrom(new_value->GetClass()));