summaryrefslogtreecommitdiff
path: root/runtime/mirror/object-inl.h
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/mirror/object-inl.h')
-rw-r--r--runtime/mirror/object-inl.h86
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>();