Refactor object reference visiting logic.
Refactored the reference visiting logic to be in mirror::Object
instead of MarkSweep.
Change-Id: I773249478dc463d83b465e85c2402320488577c0
diff --git a/runtime/gc/collector/mark_sweep-inl.h b/runtime/gc/collector/mark_sweep-inl.h
index f73a50f..1cb2adb 100644
--- a/runtime/gc/collector/mark_sweep-inl.h
+++ b/runtime/gc/collector/mark_sweep-inl.h
@@ -22,137 +22,30 @@
#include "gc/heap.h"
#include "mirror/art_field.h"
#include "mirror/class.h"
-#include "mirror/object_array.h"
+#include "mirror/object_array-inl.h"
+#include "mirror/reference.h"
namespace art {
namespace gc {
namespace collector {
-template <typename MarkVisitor>
-inline void MarkSweep::ScanObjectVisit(mirror::Object* obj, const MarkVisitor& visitor) {
+template<typename MarkVisitor, typename ReferenceVisitor>
+inline void MarkSweep::ScanObjectVisit(mirror::Object* obj, const MarkVisitor& visitor,
+ const ReferenceVisitor& ref_visitor) {
if (kIsDebugBuild && !IsMarked(obj)) {
heap_->DumpSpaces();
LOG(FATAL) << "Scanning unmarked object " << obj;
}
- // The GetClass verifies the object, don't need to reverify after.
- mirror::Class* klass = obj->GetClass();
- // IsArrayClass verifies klass.
- if (UNLIKELY(klass->IsArrayClass())) {
- if (kCountScannedTypes) {
- ++array_count_;
- }
- if (klass->IsObjectArrayClass<kVerifyNone>()) {
- VisitObjectArrayReferences(obj->AsObjectArray<mirror::Object, kVerifyNone>(), visitor);
- }
- } else if (UNLIKELY(klass == mirror::Class::GetJavaLangClass())) {
- if (kCountScannedTypes) {
+ obj->VisitReferences<false>(visitor, ref_visitor);
+ if (kCountScannedTypes) {
+ mirror::Class* klass = obj->GetClass<kVerifyNone>();
+ if (UNLIKELY(klass == mirror::Class::GetJavaLangClass())) {
++class_count_;
- }
- VisitClassReferences<false>(klass, obj, visitor);
- } else {
- if (kCountScannedTypes) {
+ } else if (UNLIKELY(klass->IsArrayClass<kVerifyNone>())) {
+ ++array_count_;
+ } else {
++other_count_;
}
- VisitInstanceFieldsReferences<false>(klass, obj, visitor);
- if (UNLIKELY(klass->IsReferenceClass<kVerifyNone>())) {
- DelayReferenceReferent(klass, obj);
- }
- }
-}
-
-template <bool kVisitClass, typename Visitor>
-inline void MarkSweep::VisitObjectReferences(mirror::Object* obj, const Visitor& visitor)
- SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_,
- Locks::mutator_lock_) {
- mirror::Class* klass = obj->GetClass();
- if (klass->IsArrayClass()) {
- if (kVisitClass) {
- visitor(obj, klass, mirror::Object::ClassOffset(), false);
- }
- if (klass->IsObjectArrayClass<kVerifyNone>()) {
- VisitObjectArrayReferences(obj->AsObjectArray<mirror::Object, kVerifyNone>(), visitor);
- }
- } else if (klass == mirror::Class::GetJavaLangClass()) {
- DCHECK_EQ(klass->GetClass<kVerifyNone>(), mirror::Class::GetJavaLangClass());
- VisitClassReferences<kVisitClass>(klass, obj, visitor);
- } else {
- VisitInstanceFieldsReferences<kVisitClass>(klass, obj, visitor);
- }
-}
-
-template <bool kVisitClass, typename Visitor>
-inline void MarkSweep::VisitInstanceFieldsReferences(mirror::Class* klass,
- mirror::Object* obj, const Visitor& visitor)
- SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
- VisitFieldsReferences<kVisitClass>(obj, klass->GetReferenceInstanceOffsets<kVerifyNone>(), false,
- visitor);
-}
-
-template <bool kVisitClass, typename Visitor>
-inline void MarkSweep::VisitClassReferences(mirror::Class* klass, mirror::Object* obj,
- const Visitor& visitor)
- SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
- VisitInstanceFieldsReferences<kVisitClass>(klass, obj, visitor);
- VisitStaticFieldsReferences<kVisitClass>(obj->AsClass<kVerifyNone>(), visitor);
-}
-
-template <bool kVisitClass, typename Visitor>
-inline void MarkSweep::VisitStaticFieldsReferences(mirror::Class* klass, const Visitor& visitor)
- SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
- VisitFieldsReferences<kVisitClass>(klass, klass->GetReferenceStaticOffsets<kVerifyNone>(), true,
- visitor);
-}
-
-template <bool kVisitClass, typename Visitor>
-inline void MarkSweep::VisitFieldsReferences(mirror::Object* obj, uint32_t ref_offsets,
- bool is_static, const Visitor& visitor) {
- if (LIKELY(ref_offsets != CLASS_WALK_SUPER)) {
- if (!kVisitClass) {
- // Currently the class bit is always set in the word. Since we count leading zeros to find
- // the offset and the class bit is at offset 0, it means that the highest bit is the class
- // bit. We can quickly clear this using xor.
- ref_offsets ^= kWordHighBitMask;
- DCHECK_EQ(mirror::Object::ClassOffset().Uint32Value(), 0U);
- }
- // Found a reference offset bitmap. Mark the specified offsets.
- while (ref_offsets != 0) {
- size_t right_shift = CLZ(ref_offsets);
- MemberOffset field_offset = CLASS_OFFSET_FROM_CLZ(right_shift);
- mirror::Object* ref = obj->GetFieldObject<mirror::Object, kVerifyReads>(field_offset, false);
- visitor(obj, ref, field_offset, is_static);
- ref_offsets &= ~(CLASS_HIGH_BIT >> right_shift);
- }
- } 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 (mirror::Class* klass = is_static ? obj->AsClass<kVerifyNone>() : obj->GetClass<kVerifyNone>();
- klass != nullptr;
- klass = is_static ? nullptr : klass->GetSuperClass()) {
- size_t num_reference_fields = (is_static
- ? klass->NumReferenceStaticFields()
- : klass->NumReferenceInstanceFields());
- for (size_t i = 0; i < num_reference_fields; ++i) {
- mirror::ArtField* field = (is_static ? klass->GetStaticField(i)
- : klass->GetInstanceField(i));
- MemberOffset field_offset = field->GetOffset();
- mirror::Object* ref = obj->GetFieldObject<mirror::Object, kVerifyReads>(field_offset, false);
- visitor(obj, ref, field_offset, is_static);
- }
- }
- }
-}
-
-template <typename Visitor>
-inline void MarkSweep::VisitObjectArrayReferences(mirror::ObjectArray<mirror::Object>* array,
- const Visitor& visitor) {
- const size_t length = static_cast<size_t>(array->GetLength());
- for (size_t i = 0; i < length; ++i) {
- mirror::Object* element = array->GetWithoutChecks(static_cast<int32_t>(i));
- const size_t width = sizeof(mirror::HeapReference<mirror::Object>);
- MemberOffset offset(i * width + mirror::Array::DataOffset(width).Int32Value());
- visitor(array, element, offset, false);
}
}