diff options
Diffstat (limited to 'runtime/mirror/object-inl.h')
-rw-r--r-- | runtime/mirror/object-inl.h | 86 |
1 files changed, 31 insertions, 55 deletions
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h index 14b9ca3af0..6a6f50347c 100644 --- a/runtime/mirror/object-inl.h +++ b/runtime/mirror/object-inl.h @@ -46,7 +46,7 @@ namespace mirror { inline uint32_t Object::ClassSize(PointerSize pointer_size) { uint32_t vtable_entries = kVTableLength; - return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0, pointer_size); + return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0, 0, pointer_size); } template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> @@ -345,6 +345,7 @@ inline bool Object::IsPhantomReferenceInstance() { return GetClass<kVerifyFlags>()->IsPhantomReferenceClass(); } +// TODO: optimize this by using class_flags_ to determine type template<VerifyObjectFlags kVerifyFlags> inline size_t Object::SizeOf() { // Read barrier is never required for SizeOf since objects sizes are constant. Reading from-space @@ -858,65 +859,40 @@ inline void Object::UpdateField64ViaAccessor(MemberOffset field_offset, accessor->Access(addr); } -template<bool kIsStatic, - VerifyObjectFlags kVerifyFlags, - ReadBarrierOption kReadBarrierOption, - typename Visitor> -inline void Object::VisitFieldsReferences(uint32_t ref_offsets, const Visitor& visitor) { - if (!kIsStatic && (ref_offsets != mirror::Class::kClassWalkSuper)) { - // Instance fields and not the slow-path. - uint32_t field_offset = mirror::kObjectHeaderSize; - while (ref_offsets != 0) { - if ((ref_offsets & 1) != 0) { - visitor(this, MemberOffset(field_offset), kIsStatic); - } - ref_offsets >>= 1; - field_offset += sizeof(mirror::HeapReference<mirror::Object>); +template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, typename Visitor> +inline void Object::VisitInstanceFieldsReferences(ObjPtr<Class> klass, const Visitor& visitor) { + // Using NO_THREAD_SAFETY_ANALYSIS as heap_bitmap_lock_ and mutator_lock_ are + // required in shared/exclusive modes in all possible combinations. + auto visit_one_word = [&visitor, this](uint32_t field_offset, uint32_t ref_offsets) + NO_THREAD_SAFETY_ANALYSIS { + while (ref_offsets != 0) { + if ((ref_offsets & 1) != 0) { + visitor(this, MemberOffset(field_offset), /*is_static=*/false); + } + ref_offsets >>= 1; + field_offset += sizeof(HeapReference<Object>); + } + }; + + uint32_t ref_offsets = klass->GetReferenceInstanceOffsets<kVerifyFlags>(); + DCHECK_NE(ref_offsets, 0u) << klass->PrettyDescriptor(); + if (UNLIKELY((ref_offsets & Class::kVisitReferencesSlowpathMask) != 0)) { + if (kIsDebugBuild) { + klass->VerifyOverflowReferenceBitmap<kVerifyFlags, kReadBarrierOption>(); } - } else { - // There is no reference offset bitmap. In the non-static case, walk up the class - // inheritance hierarchy and find reference offsets the hard way. In the static case, just - // consider this class. - for (ObjPtr<Class> klass = kIsStatic - ? ObjPtr<Class>::DownCast(this) - : GetClass<kVerifyFlags, kReadBarrierOption>(); - klass != nullptr; - klass = kIsStatic ? nullptr : klass->GetSuperClass<kVerifyFlags, kReadBarrierOption>()) { - const size_t num_reference_fields = - kIsStatic ? klass->NumReferenceStaticFields() : klass->NumReferenceInstanceFields(); - if (num_reference_fields == 0u) { - continue; - } - // Presumably GC can happen when we are cross compiling, it should not cause performance - // problems to do pointer size logic. - MemberOffset field_offset = kIsStatic - ? klass->GetFirstReferenceStaticFieldOffset<kVerifyFlags>( - Runtime::Current()->GetClassLinker()->GetImagePointerSize()) - : klass->GetFirstReferenceInstanceFieldOffset<kVerifyFlags, kReadBarrierOption>(); - for (size_t i = 0u; i < num_reference_fields; ++i) { - // TODO: Do a simpler check? - if (field_offset.Uint32Value() != ClassOffset().Uint32Value()) { - visitor(this, field_offset, kIsStatic); - } - field_offset = MemberOffset(field_offset.Uint32Value() + - sizeof(mirror::HeapReference<mirror::Object>)); - } + uint32_t bitmap_num_words = ref_offsets & ~Class::kVisitReferencesSlowpathMask; + uint32_t* overflow_bitmap = reinterpret_cast<uint32_t*>( + reinterpret_cast<uint8_t*>(klass.Ptr()) + + (klass->GetClassSize<kVerifyFlags>() - bitmap_num_words * sizeof(uint32_t))); + for (uint32_t i = 0; i < bitmap_num_words; i++) { + visit_one_word(kObjectHeaderSize + i * sizeof(HeapReference<Object>) * 32, + overflow_bitmap[i]); } + } else { + visit_one_word(mirror::kObjectHeaderSize, ref_offsets); } } -template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, typename Visitor> -inline void Object::VisitInstanceFieldsReferences(ObjPtr<Class> klass, const Visitor& visitor) { - VisitFieldsReferences<false, kVerifyFlags, kReadBarrierOption>( - klass->GetReferenceInstanceOffsets<kVerifyFlags>(), visitor); -} - -template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, typename Visitor> -inline void Object::VisitStaticFieldsReferences(ObjPtr<Class> klass, const Visitor& visitor) { - DCHECK(!klass->IsTemp<kVerifyFlags>()); - klass->VisitFieldsReferences<true, kVerifyFlags, kReadBarrierOption>(0, visitor); -} - template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> inline bool Object::IsClassLoader() { return GetClass<kVerifyFlags, kReadBarrierOption>()->template IsClassLoaderClass<kVerifyFlags>(); |