diff options
author | Vladimir Marko <vmarko@google.com> | 2014-11-10 18:32:59 +0000 |
---|---|---|
committer | Vladimir Marko <vmarko@google.com> | 2014-11-14 11:33:53 +0000 |
commit | 76649e8d775519fe19f2b14d18ac488c13296054 (patch) | |
tree | a899ec37ce51672c9e14d2954b2a7af7397e63da /runtime | |
parent | d94a0a1d2868baaab49f4d2835bca086d98cf763 (diff) | |
download | art-76649e8d775519fe19f2b14d18ac488c13296054.zip art-76649e8d775519fe19f2b14d18ac488c13296054.tar.gz art-76649e8d775519fe19f2b14d18ac488c13296054.tar.bz2 |
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
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/class_linker.cc | 132 | ||||
-rw-r--r-- | runtime/class_linker_test.cc | 99 | ||||
-rw-r--r-- | runtime/mirror/class-inl.h | 30 | ||||
-rw-r--r-- | runtime/mirror/class.h | 10 | ||||
-rw-r--r-- | runtime/mirror/object-inl.h | 10 | ||||
-rw-r--r-- | runtime/mirror/object.cc | 10 |
6 files changed, 162 insertions, 129 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index fb90b91..5afba62 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -185,15 +185,13 @@ static void AddFieldGap(uint32_t gap_start, uint32_t gap_end, FieldGaps* gaps) { } // Shuffle fields forward, making use of gaps whenever possible. template<int n> -static void ShuffleForward(const size_t num_fields, size_t* current_field_idx, +static void ShuffleForward(size_t* current_field_idx, MemberOffset* field_offset, - mirror::ObjectArray<mirror::ArtField>* fields, std::deque<mirror::ArtField*>* grouped_and_sorted_fields, FieldGaps* gaps) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { DCHECK(current_field_idx != nullptr); DCHECK(grouped_and_sorted_fields != nullptr); - DCHECK(fields != nullptr || (num_fields == 0 && grouped_and_sorted_fields->empty())); DCHECK(gaps != nullptr); DCHECK(field_offset != nullptr); @@ -211,7 +209,6 @@ static void ShuffleForward(const size_t num_fields, size_t* current_field_idx, } CHECK(type != Primitive::kPrimNot) << PrettyField(field); // should be primitive types grouped_and_sorted_fields->pop_front(); - fields->Set<false>(*current_field_idx, field); if (!gaps->empty() && gaps->top().size >= n) { FieldGap gap = gaps->top(); gaps->pop(); @@ -5231,13 +5228,7 @@ bool ClassLinker::LinkFields(Thread* self, Handle<mirror::Class> klass, bool is_ // Initialize field_offset MemberOffset field_offset(0); if (is_static) { - uint32_t base = sizeof(mirror::Class); // Static fields come after the class. - if (klass->ShouldHaveEmbeddedImtAndVTable()) { - // Static fields come after the embedded tables. - base = mirror::Class::ComputeClassSize(true, klass->GetVTableDuringLinking()->GetLength(), - 0, 0, 0, 0, 0); - } - field_offset = MemberOffset(base); + field_offset = klass->GetFirstReferenceStaticFieldOffsetDuringLinking(); } else { mirror::Class* super_class = klass->GetSuperClass(); if (super_class != nullptr) { @@ -5274,28 +5265,25 @@ bool ClassLinker::LinkFields(Thread* self, Handle<mirror::Class> klass, bool is_ if (isPrimitive) { break; // past last reference, move on to the next phase } - if (UNLIKELY(!IsAligned<4>(field_offset.Uint32Value()))) { + if (UNLIKELY(!IsAligned<sizeof(mirror::HeapReference<mirror::Object>)>( + field_offset.Uint32Value()))) { MemberOffset old_offset = field_offset; field_offset = MemberOffset(RoundUp(field_offset.Uint32Value(), 4)); AddFieldGap(old_offset.Uint32Value(), field_offset.Uint32Value(), &gaps); } - DCHECK(IsAligned<4>(field_offset.Uint32Value())); + DCHECK(IsAligned<sizeof(mirror::HeapReference<mirror::Object>)>(field_offset.Uint32Value())); grouped_and_sorted_fields.pop_front(); num_reference_fields++; - fields->Set<false>(current_field, field); field->SetOffset(field_offset); - field_offset = MemberOffset(field_offset.Uint32Value() + sizeof(uint32_t)); + field_offset = MemberOffset(field_offset.Uint32Value() + + sizeof(mirror::HeapReference<mirror::Object>)); } // Gaps are stored as a max heap which means that we must shuffle from largest to smallest // otherwise we could end up with suboptimal gap fills. - ShuffleForward<8>(num_fields, ¤t_field, &field_offset, - fields, &grouped_and_sorted_fields, &gaps); - ShuffleForward<4>(num_fields, ¤t_field, &field_offset, - fields, &grouped_and_sorted_fields, &gaps); - ShuffleForward<2>(num_fields, ¤t_field, &field_offset, - fields, &grouped_and_sorted_fields, &gaps); - ShuffleForward<1>(num_fields, ¤t_field, &field_offset, - fields, &grouped_and_sorted_fields, &gaps); + ShuffleForward<8>(¤t_field, &field_offset, &grouped_and_sorted_fields, &gaps); + ShuffleForward<4>(¤t_field, &field_offset, &grouped_and_sorted_fields, &gaps); + ShuffleForward<2>(¤t_field, &field_offset, &grouped_and_sorted_fields, &gaps); + ShuffleForward<1>(¤t_field, &field_offset, &grouped_and_sorted_fields, &gaps); CHECK(grouped_and_sorted_fields.empty()) << "Missed " << grouped_and_sorted_fields.size() << " fields."; self->EndAssertNoThreadSuspension(old_no_suspend_cause); @@ -5309,10 +5297,35 @@ bool ClassLinker::LinkFields(Thread* self, Handle<mirror::Class> klass, bool is_ --num_reference_fields; } + size_t size = field_offset.Uint32Value(); + // Update klass + if (is_static) { + klass->SetNumReferenceStaticFields(num_reference_fields); + *class_size = size; + } else { + klass->SetNumReferenceInstanceFields(num_reference_fields); + if (!klass->IsVariableSize()) { + std::string temp; + DCHECK_GE(size, sizeof(mirror::Object)) << klass->GetDescriptor(&temp); + size_t previous_size = klass->GetObjectSize(); + if (previous_size != 0) { + // Make sure that we didn't originally have an incorrect size. + CHECK_EQ(previous_size, size) << klass->GetDescriptor(&temp); + } + klass->SetObjectSize(size); + } + } + if (kIsDebugBuild) { - // Make sure that all reference fields appear before - // non-reference fields, and all double-wide fields are aligned. - bool seen_non_ref = false; + // Make sure that the fields array is ordered by name but all reference + // offsets are at the beginning as far as alignment allows. + MemberOffset start_ref_offset = is_static + ? klass->GetFirstReferenceStaticFieldOffsetDuringLinking() + : klass->GetFirstReferenceInstanceFieldOffset(); + MemberOffset end_ref_offset(start_ref_offset.Uint32Value() + + num_reference_fields * + sizeof(mirror::HeapReference<mirror::Object>)); + MemberOffset current_ref_offset = start_ref_offset; for (size_t i = 0; i < num_fields; i++) { mirror::ArtField* field = fields->Get(i); if ((false)) { // enable to debug field layout @@ -5322,49 +5335,39 @@ bool ClassLinker::LinkFields(Thread* self, Handle<mirror::Class> klass, bool is_ << " offset=" << field->GetField32(mirror::ArtField::OffsetOffset()); } + if (i != 0) { + mirror::ArtField* prev_field = fields->Get(i - 1u); + CHECK_LT(strcmp(prev_field->GetName(), field->GetName()), 0); + } Primitive::Type type = field->GetTypeAsPrimitiveType(); bool is_primitive = type != Primitive::kPrimNot; if (klass->DescriptorEquals("Ljava/lang/ref/Reference;") && strcmp("referent", field->GetName()) == 0) { is_primitive = true; // We lied above, so we have to expect a lie here. } + MemberOffset offset = field->GetOffsetDuringLinking(); if (is_primitive) { - if (!seen_non_ref) { - seen_non_ref = true; - DCHECK_EQ(num_reference_fields, i) << PrettyField(field); + if (offset.Uint32Value() < end_ref_offset.Uint32Value()) { + // Shuffled before references. + size_t type_size = Primitive::ComponentSize(type); + CHECK_LT(type_size, sizeof(mirror::HeapReference<mirror::Object>)); + CHECK_LT(offset.Uint32Value(), start_ref_offset.Uint32Value()); + CHECK_LE(offset.Uint32Value() + type_size, start_ref_offset.Uint32Value()); + CHECK(!IsAligned<sizeof(mirror::HeapReference<mirror::Object>)>(offset.Uint32Value())); } } else { - DCHECK(!seen_non_ref) << PrettyField(field); + CHECK_EQ(current_ref_offset.Uint32Value(), offset.Uint32Value()); + current_ref_offset = MemberOffset(current_ref_offset.Uint32Value() + + sizeof(mirror::HeapReference<mirror::Object>)); } } - if (!seen_non_ref) { - DCHECK_EQ(num_fields, num_reference_fields) << PrettyClass(klass.Get()); - } + CHECK_EQ(current_ref_offset.Uint32Value(), end_ref_offset.Uint32Value()); } - size_t size = field_offset.Uint32Value(); - // Update klass - if (is_static) { - klass->SetNumReferenceStaticFields(num_reference_fields); - *class_size = size; - } else { - klass->SetNumReferenceInstanceFields(num_reference_fields); - if (!klass->IsVariableSize()) { - std::string temp; - DCHECK_GE(size, sizeof(mirror::Object)) << klass->GetDescriptor(&temp); - size_t previous_size = klass->GetObjectSize(); - if (previous_size != 0) { - // Make sure that we didn't originally have an incorrect size. - CHECK_EQ(previous_size, size) << klass->GetDescriptor(&temp); - } - klass->SetObjectSize(size); - } - } return true; } -// Set the bitmap of reference offsets, refOffsets, from the ifields -// list. +// Set the bitmap of reference instance field offsets. void ClassLinker::CreateReferenceInstanceOffsets(Handle<mirror::Class> klass) { uint32_t reference_offsets = 0; mirror::Class* super_class = klass->GetSuperClass(); @@ -5374,23 +5377,18 @@ void ClassLinker::CreateReferenceInstanceOffsets(Handle<mirror::Class> klass) { // Compute reference offsets unless our superclass overflowed. if (reference_offsets != mirror::Class::kClassWalkSuper) { size_t num_reference_fields = klass->NumReferenceInstanceFieldsDuringLinking(); - mirror::ObjectArray<mirror::ArtField>* fields = klass->GetIFields(); - // All of the fields that contain object references are guaranteed - // to be at the beginning of the fields list. - for (size_t i = 0; i < num_reference_fields; ++i) { - // Note that byte_offset is the offset from the beginning of - // object, not the offset into instance data - mirror::ArtField* field = fields->Get(i); - MemberOffset byte_offset = field->GetOffsetDuringLinking(); - uint32_t displaced_bitmap_position = - (byte_offset.Uint32Value() - mirror::kObjectHeaderSize) / + if (num_reference_fields != 0u) { + // All of the fields that contain object references are guaranteed be grouped in memory + // starting at an appropriately aligned address after super class object data. + uint32_t start_offset = RoundUp(super_class->GetObjectSize(), + sizeof(mirror::HeapReference<mirror::Object>)); + uint32_t start_bit = (start_offset - mirror::kObjectHeaderSize) / sizeof(mirror::HeapReference<mirror::Object>); - if (displaced_bitmap_position >= 32) { - // Can't encode offset so fall back on slow-path. + if (start_bit + num_reference_fields > 32) { reference_offsets = mirror::Class::kClassWalkSuper; - break; } else { - reference_offsets |= (1 << displaced_bitmap_position); + reference_offsets |= (0xffffffffu << start_bit) & + (0xffffffffu >> (32 - (start_bit + num_reference_fields))); } } } diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc index b257343..ba5aa3d 100644 --- a/runtime/class_linker_test.cc +++ b/runtime/class_linker_test.cc @@ -275,31 +275,42 @@ class ClassLinkerTest : public CommonRuntimeTest { EXPECT_TRUE(field->IsStatic()); } - // Confirm that all instances fields are packed together at the start + // Confirm that all instances field offsets are packed together at the start. EXPECT_GE(klass->NumInstanceFields(), klass->NumReferenceInstanceFields()); StackHandleScope<1> hs(Thread::Current()); MutableHandle<mirror::ArtField> fhandle = hs.NewHandle<mirror::ArtField>(nullptr); - for (size_t i = 0; i < klass->NumReferenceInstanceFields(); i++) { - mirror::ArtField* field = klass->GetInstanceField(i); - fhandle.Assign(field); - FieldHelper fh(fhandle); - ASSERT_TRUE(!field->IsPrimitiveType()); - mirror::Class* field_type = fh.GetType(); - ASSERT_TRUE(field_type != nullptr); - ASSERT_TRUE(!field_type->IsPrimitive()); - } - for (size_t i = klass->NumReferenceInstanceFields(); i < klass->NumInstanceFields(); i++) { + 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++) { mirror::ArtField* field = klass->GetInstanceField(i); fhandle.Assign(field); FieldHelper fh(fhandle); mirror::Class* field_type = fh.GetType(); ASSERT_TRUE(field_type != nullptr); - if (!fh.GetField()->IsPrimitiveType() || !field_type->IsPrimitive()) { - // While Reference.referent is not primitive, the ClassLinker - // treats it as such so that the garbage collector won't scan it. - EXPECT_EQ(PrettyField(fh.GetField()), "java.lang.Object java.lang.ref.Reference.referent"); + if (!field->IsPrimitiveType()) { + ASSERT_TRUE(!field_type->IsPrimitive()); + ASSERT_EQ(current_ref_offset.Uint32Value(), field->GetOffset().Uint32Value()); + if (current_ref_offset.Uint32Value() == end_ref_offset.Uint32Value()) { + // While Reference.referent is not primitive, the ClassLinker + // treats it as such so that the garbage collector won't scan it. + EXPECT_EQ(PrettyField(fh.GetField()), + "java.lang.Object java.lang.ref.Reference.referent"); + } else { + current_ref_offset = MemberOffset(current_ref_offset.Uint32Value() + + sizeof(mirror::HeapReference<mirror::Object>)); + } + } else { + if (field->GetOffset().Uint32Value() < end_ref_offset.Uint32Value()) { + // Shuffled before references. + ASSERT_LT(field->GetOffset().Uint32Value(), start_ref_offset.Uint32Value()); + CHECK(!IsAligned<4>(field->GetOffset().Uint32Value())); + } } } + ASSERT_EQ(end_ref_offset.Uint32Value(), current_ref_offset.Uint32Value()); uint32_t total_num_reference_instance_fields = 0; mirror::Class* k = klass.Get(); @@ -461,10 +472,7 @@ struct CheckOffsets { struct ObjectOffsets : public CheckOffsets<mirror::Object> { ObjectOffsets() : CheckOffsets<mirror::Object>(false, "Ljava/lang/Object;") { - // alphabetical references offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Object, klass_), "shadow$_klass_")); - - // alphabetical 32-bit offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Object, monitor_), "shadow$_monitor_")); #ifdef USE_BAKER_OR_BROOKS_READ_BARRIER offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Object, x_rb_ptr_), "shadow$_x_rb_ptr_")); @@ -475,11 +483,8 @@ struct ObjectOffsets : public CheckOffsets<mirror::Object> { struct ArtFieldOffsets : public CheckOffsets<mirror::ArtField> { ArtFieldOffsets() : CheckOffsets<mirror::ArtField>(false, "Ljava/lang/reflect/ArtField;") { - // alphabetical references - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtField, declaring_class_), "declaringClass")); - - // alphabetical 32-bit offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtField, access_flags_), "accessFlags")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtField, declaring_class_), "declaringClass")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtField, field_dex_idx_), "fieldDexIndex")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtField, offset_), "offset")); }; @@ -487,73 +492,61 @@ struct ArtFieldOffsets : public CheckOffsets<mirror::ArtField> { struct ArtMethodOffsets : public CheckOffsets<mirror::ArtMethod> { ArtMethodOffsets() : CheckOffsets<mirror::ArtMethod>(false, "Ljava/lang/reflect/ArtMethod;") { - // alphabetical references + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, access_flags_), "accessFlags")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, declaring_class_), "declaringClass")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_cache_resolved_methods_), "dexCacheResolvedMethods")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_cache_resolved_types_), "dexCacheResolvedTypes")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_cache_strings_), "dexCacheStrings")); - - // alphabetical 64-bit + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_code_item_offset_), "dexCodeItemOffset")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_method_index_), "dexMethodIndex")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, entry_point_from_interpreter_), "entryPointFromInterpreter")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, entry_point_from_jni_), "entryPointFromJni")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, entry_point_from_portable_compiled_code_), "entryPointFromPortableCompiledCode")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, entry_point_from_quick_compiled_code_), "entryPointFromQuickCompiledCode")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, gc_map_), "gcMap")); - - // alphabetical 32-bit - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, access_flags_), "accessFlags")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_code_item_offset_), "dexCodeItemOffset")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_method_index_), "dexMethodIndex")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, method_index_), "methodIndex")); }; }; struct ClassOffsets : public CheckOffsets<mirror::Class> { ClassOffsets() : CheckOffsets<mirror::Class>(false, "Ljava/lang/Class;") { - // alphabetical references + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, access_flags_), "accessFlags")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, class_loader_), "classLoader")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, class_size_), "classSize")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, clinit_thread_id_), "clinitThreadId")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, component_type_), "componentType")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, dex_cache_), "dexCache")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, dex_class_def_idx_), "dexClassDefIndex")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, dex_type_idx_), "dexTypeIndex")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, direct_methods_), "directMethods")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, ifields_), "iFields")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, iftable_), "ifTable")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, name_), "name")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, sfields_), "sFields")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, super_class_), "superClass")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, verify_error_class_), "verifyErrorClass")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, virtual_methods_), "virtualMethods")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, vtable_), "vtable")); - - // alphabetical 32-bit - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, access_flags_), "accessFlags")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, class_size_), "classSize")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, clinit_thread_id_), "clinitThreadId")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, dex_class_def_idx_), "dexClassDefIndex")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, dex_type_idx_), "dexTypeIndex")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, num_reference_instance_fields_), "numReferenceInstanceFields")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, num_reference_static_fields_), "numReferenceStaticFields")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, object_size_), "objectSize")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, primitive_type_), "primitiveType")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, reference_instance_offsets_), "referenceInstanceOffsets")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, sfields_), "sFields")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, status_), "status")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, super_class_), "superClass")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, verify_error_class_), "verifyErrorClass")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, virtual_methods_), "virtualMethods")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, vtable_), "vtable")); }; }; struct StringOffsets : public CheckOffsets<mirror::String> { StringOffsets() : CheckOffsets<mirror::String>(false, "Ljava/lang/String;") { - // alphabetical references - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::String, array_), "value")); - - // alphabetical 32-bit offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::String, count_), "count")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::String, hash_code_), "hashCode")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::String, offset_), "offset")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::String, array_), "value")); }; }; struct ThrowableOffsets : public CheckOffsets<mirror::Throwable> { ThrowableOffsets() : CheckOffsets<mirror::Throwable>(false, "Ljava/lang/Throwable;") { - // alphabetical references offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Throwable, cause_), "cause")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Throwable, detail_message_), "detailMessage")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Throwable, stack_state_), "stackState")); @@ -564,17 +557,15 @@ struct ThrowableOffsets : public CheckOffsets<mirror::Throwable> { struct StackTraceElementOffsets : public CheckOffsets<mirror::StackTraceElement> { StackTraceElementOffsets() : CheckOffsets<mirror::StackTraceElement>(false, "Ljava/lang/StackTraceElement;") { - // alphabetical references offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::StackTraceElement, declaring_class_), "declaringClass")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::StackTraceElement, file_name_), "fileName")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::StackTraceElement, method_name_), "methodName")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::StackTraceElement, line_number_), "lineNumber")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::StackTraceElement, method_name_), "methodName")); }; }; struct ClassLoaderOffsets : public CheckOffsets<mirror::ClassLoader> { ClassLoaderOffsets() : CheckOffsets<mirror::ClassLoader>(false, "Ljava/lang/ClassLoader;") { - // alphabetical references offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ClassLoader, packages_), "packages")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ClassLoader, parent_), "parent")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ClassLoader, proxyCache_), "proxyCache")); @@ -583,27 +574,24 @@ struct ClassLoaderOffsets : public CheckOffsets<mirror::ClassLoader> { struct ProxyOffsets : public CheckOffsets<mirror::Proxy> { ProxyOffsets() : CheckOffsets<mirror::Proxy>(false, "Ljava/lang/reflect/Proxy;") { - // alphabetical references offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Proxy, h_), "h")); }; }; struct DexCacheOffsets : public CheckOffsets<mirror::DexCache> { DexCacheOffsets() : CheckOffsets<mirror::DexCache>(false, "Ljava/lang/DexCache;") { - // alphabetical references offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::DexCache, dex_), "dex")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::DexCache, dex_file_), "dexFile")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::DexCache, location_), "location")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::DexCache, resolved_fields_), "resolvedFields")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::DexCache, resolved_methods_), "resolvedMethods")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::DexCache, resolved_types_), "resolvedTypes")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::DexCache, strings_), "strings")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::DexCache, dex_file_), "dexFile")); }; }; struct ReferenceOffsets : public CheckOffsets<mirror::Reference> { ReferenceOffsets() : CheckOffsets<mirror::Reference>(false, "Ljava/lang/ref/Reference;") { - // alphabetical references offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Reference, pending_next_), "pendingNext")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Reference, queue_), "queue")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Reference, queue_next_), "queueNext")); @@ -613,7 +601,6 @@ struct ReferenceOffsets : public CheckOffsets<mirror::Reference> { struct FinalizerReferenceOffsets : public CheckOffsets<mirror::FinalizerReference> { FinalizerReferenceOffsets() : CheckOffsets<mirror::FinalizerReference>(false, "Ljava/lang/ref/FinalizerReference;") { - // alphabetical references offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::FinalizerReference, next_), "next")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::FinalizerReference, prev_), "prev")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::FinalizerReference, zombie_), "zombie")); 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 @@ inline ObjectArray<ArtField>* Class::GetIFields() { 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 @@ class MANAGED Class FINAL : public Object { 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 @@ class MANAGED Class FINAL : public Object { 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 @@ inline void Object::VisitFieldsReferences(uint32_t ref_offsets, const Visitor& v 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 @@ void Object::CheckFieldAssignmentImpl(MemberOffset field_offset, Object* new_val 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 @@ void Object::CheckFieldAssignmentImpl(MemberOffset field_offset, Object* new_val 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())); |