summaryrefslogtreecommitdiffstats
path: root/runtime/gc
diff options
context:
space:
mode:
authorMathieu Chartier <mathieuc@google.com>2014-02-18 14:37:05 -0800
committerMathieu Chartier <mathieuc@google.com>2014-03-24 16:35:21 -0700
commit407f702da4f867c074fc3c8c688b8f8c32279eff (patch)
tree6a856b64f655f5aab1c538eab28e9c69f9010122 /runtime/gc
parentd201dec03334bcc25add81704981a78c19927d87 (diff)
downloadart-407f702da4f867c074fc3c8c688b8f8c32279eff.zip
art-407f702da4f867c074fc3c8c688b8f8c32279eff.tar.gz
art-407f702da4f867c074fc3c8c688b8f8c32279eff.tar.bz2
Refactor object reference visiting logic.
Refactored the reference visiting logic to be in mirror::Object instead of MarkSweep. Change-Id: I773249478dc463d83b465e85c2402320488577c0
Diffstat (limited to 'runtime/gc')
-rw-r--r--runtime/gc/accounting/mod_union_table.cc80
-rw-r--r--runtime/gc/accounting/mod_union_table.h6
-rw-r--r--runtime/gc/accounting/remembered_set.cc32
-rw-r--r--runtime/gc/accounting/remembered_set.h2
-rw-r--r--runtime/gc/collector/mark_sweep-inl.h131
-rw-r--r--runtime/gc/collector/mark_sweep.cc103
-rw-r--r--runtime/gc/collector/mark_sweep.h64
-rw-r--r--runtime/gc/collector/semi_space.cc116
-rw-r--r--runtime/gc/collector/semi_space.h25
-rw-r--r--runtime/gc/heap.cc61
10 files changed, 253 insertions, 367 deletions
diff --git a/runtime/gc/accounting/mod_union_table.cc b/runtime/gc/accounting/mod_union_table.cc
index 8bc1ced..314f3c5 100644
--- a/runtime/gc/accounting/mod_union_table.cc
+++ b/runtime/gc/accounting/mod_union_table.cc
@@ -70,37 +70,29 @@ class ModUnionClearCardVisitor {
class ModUnionUpdateObjectReferencesVisitor {
public:
- ModUnionUpdateObjectReferencesVisitor(MarkObjectCallback* callback, void* arg)
+ ModUnionUpdateObjectReferencesVisitor(MarkHeapReferenceCallback* callback, void* arg)
: callback_(callback),
arg_(arg) {
}
// Extra parameters are required since we use this same visitor signature for checking objects.
- void operator()(Object* obj, Object* ref, const MemberOffset& offset,
- bool /* is_static */) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ void operator()(Object* obj, MemberOffset offset, bool /* static */) const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// Only add the reference if it is non null and fits our criteria.
- if (ref != nullptr) {
- Object* new_ref = callback_(ref, arg_);
- if (new_ref != ref) {
- // Use SetFieldObjectWithoutWriteBarrier to avoid card mark as an optimization which
- // reduces dirtied pages and improves performance.
- if (Runtime::Current()->IsActiveTransaction()) {
- obj->SetFieldObjectWithoutWriteBarrier<true>(offset, new_ref, true);
- } else {
- obj->SetFieldObjectWithoutWriteBarrier<false>(offset, new_ref, true);
- }
- }
+ mirror::HeapReference<Object>* obj_ptr = obj->GetFieldObjectReferenceAddr(offset);
+ if (obj_ptr->AsMirrorPtr() != nullptr) {
+ callback_(obj_ptr, arg_);
}
}
private:
- MarkObjectCallback* const callback_;
+ MarkHeapReferenceCallback* const callback_;
void* arg_;
};
class ModUnionScanImageRootVisitor {
public:
- ModUnionScanImageRootVisitor(MarkObjectCallback* callback, void* arg)
+ ModUnionScanImageRootVisitor(MarkHeapReferenceCallback* callback, void* arg)
: callback_(callback), arg_(arg) {}
void operator()(Object* root) const
@@ -108,11 +100,11 @@ class ModUnionScanImageRootVisitor {
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(root != NULL);
ModUnionUpdateObjectReferencesVisitor ref_visitor(callback_, arg_);
- collector::MarkSweep::VisitObjectReferences<kMovingClasses>(root, ref_visitor);
+ root->VisitReferences<kMovingClasses>(ref_visitor);
}
private:
- MarkObjectCallback* const callback_;
+ MarkHeapReferenceCallback* const callback_;
void* const arg_;
};
@@ -131,12 +123,14 @@ class AddToReferenceArrayVisitor {
}
// Extra parameters are required since we use this same visitor signature for checking objects.
- void operator()(Object* obj, Object* ref, const MemberOffset& offset,
- bool /* is_static */) const {
+ void operator()(Object* obj, MemberOffset offset, bool /* static */) const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ mirror::HeapReference<Object>* ref_ptr = obj->GetFieldObjectReferenceAddr(offset);
+ mirror::Object* ref = ref_ptr->AsMirrorPtr();
// Only add the reference if it is non null and fits our criteria.
- if (ref != nullptr && mod_union_table_->AddReference(obj, ref)) {
+ if (ref != nullptr && mod_union_table_->AddReference(obj, ref)) {
// Push the adddress of the reference.
- references_->push_back(obj->GetFieldObjectReferenceAddr(offset));
+ references_->push_back(ref_ptr);
}
}
@@ -155,11 +149,10 @@ class ModUnionReferenceVisitor {
void operator()(Object* obj) const
SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
- DCHECK(obj != NULL);
// We don't have an early exit since we use the visitor pattern, an early
// exit should significantly speed this up.
AddToReferenceArrayVisitor visitor(mod_union_table_, references_);
- collector::MarkSweep::VisitObjectReferences<kMovingClasses>(obj, visitor);
+ obj->VisitReferences<kMovingClasses>(visitor);
}
private:
ModUnionTableReferenceCache* const mod_union_table_;
@@ -175,20 +168,22 @@ class CheckReferenceVisitor {
}
// Extra parameters are required since we use this same visitor signature for checking objects.
- void operator()(Object* obj, Object* ref,
- const MemberOffset& /* offset */, bool /* is_static */) const
+ void operator()(Object* obj, MemberOffset offset, bool /* is_static */) const
SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
- Heap* heap = mod_union_table_->GetHeap();
- if (ref != NULL && mod_union_table_->AddReference(obj, ref) &&
+ mirror::Object* ref = obj->GetFieldObject<mirror::Object>(offset, false);
+ if (ref != nullptr && mod_union_table_->AddReference(obj, ref) &&
references_.find(ref) == references_.end()) {
+ Heap* heap = mod_union_table_->GetHeap();
space::ContinuousSpace* from_space = heap->FindContinuousSpaceFromObject(obj, false);
space::ContinuousSpace* to_space = heap->FindContinuousSpaceFromObject(ref, false);
- LOG(INFO) << "Object " << reinterpret_cast<const void*>(obj) << "(" << PrettyTypeOf(obj) << ")"
- << "References " << reinterpret_cast<const void*>(ref)
- << "(" << PrettyTypeOf(ref) << ") without being in mod-union table";
- LOG(INFO) << "FromSpace " << from_space->GetName() << " type " << from_space->GetGcRetentionPolicy();
- LOG(INFO) << "ToSpace " << to_space->GetName() << " type " << to_space->GetGcRetentionPolicy();
- mod_union_table_->GetHeap()->DumpSpaces();
+ LOG(INFO) << "Object " << reinterpret_cast<const void*>(obj) << "(" << PrettyTypeOf(obj)
+ << ")" << "References " << reinterpret_cast<const void*>(ref) << "(" << PrettyTypeOf(ref)
+ << ") without being in mod-union table";
+ LOG(INFO) << "FromSpace " << from_space->GetName() << " type "
+ << from_space->GetGcRetentionPolicy();
+ LOG(INFO) << "ToSpace " << to_space->GetName() << " type "
+ << to_space->GetGcRetentionPolicy();
+ heap->DumpSpaces();
LOG(FATAL) << "FATAL ERROR";
}
}
@@ -208,9 +203,8 @@ class ModUnionCheckReferences {
void operator()(Object* obj) const NO_THREAD_SAFETY_ANALYSIS {
Locks::heap_bitmap_lock_->AssertSharedHeld(Thread::Current());
- DCHECK(obj != NULL);
CheckReferenceVisitor visitor(mod_union_table_, references_);
- collector::MarkSweep::VisitObjectReferences<kMovingClasses>(obj, visitor);
+ obj->VisitReferences<kMovingClasses>(visitor);
}
private:
@@ -264,7 +258,7 @@ void ModUnionTableReferenceCache::Dump(std::ostream& os) {
}
}
-void ModUnionTableReferenceCache::UpdateAndMarkReferences(MarkObjectCallback* callback,
+void ModUnionTableReferenceCache::UpdateAndMarkReferences(MarkHeapReferenceCallback* callback,
void* arg) {
Heap* heap = GetHeap();
CardTable* card_table = heap->GetCardTable();
@@ -298,14 +292,7 @@ void ModUnionTableReferenceCache::UpdateAndMarkReferences(MarkObjectCallback* ca
size_t count = 0;
for (const auto& ref : references_) {
for (mirror::HeapReference<Object>* obj_ptr : ref.second) {
- Object* obj = obj_ptr->AsMirrorPtr();
- if (obj != nullptr) {
- Object* new_obj = callback(obj, arg);
- // Avoid dirtying pages in the image unless necessary.
- if (new_obj != obj) {
- obj_ptr->Assign(new_obj);
- }
- }
+ callback(obj_ptr, arg);
}
count += ref.second.size();
}
@@ -322,7 +309,8 @@ void ModUnionTableCardCache::ClearCards() {
}
// Mark all references to the alloc space(s).
-void ModUnionTableCardCache::UpdateAndMarkReferences(MarkObjectCallback* callback, void* arg) {
+void ModUnionTableCardCache::UpdateAndMarkReferences(MarkHeapReferenceCallback* callback,
+ void* arg) {
CardTable* card_table = heap_->GetCardTable();
ModUnionScanImageRootVisitor scan_visitor(callback, arg);
SpaceBitmap* bitmap = space_->GetLiveBitmap();
diff --git a/runtime/gc/accounting/mod_union_table.h b/runtime/gc/accounting/mod_union_table.h
index 2e22a11..c4b020b 100644
--- a/runtime/gc/accounting/mod_union_table.h
+++ b/runtime/gc/accounting/mod_union_table.h
@@ -69,7 +69,7 @@ class ModUnionTable {
// Update the mod-union table using data stored by ClearCards. There may be multiple ClearCards
// before a call to update, for example, back-to-back sticky GCs. Also mark references to other
// spaces which are stored in the mod-union table.
- virtual void UpdateAndMarkReferences(MarkObjectCallback* callback, void* arg) = 0;
+ virtual void UpdateAndMarkReferences(MarkHeapReferenceCallback* callback, void* arg) = 0;
// Verification, sanity checks that we don't have clean cards which conflict with out cached data
// for said cards. Exclusive lock is required since verify sometimes uses
@@ -106,7 +106,7 @@ class ModUnionTableReferenceCache : public ModUnionTable {
void ClearCards();
// Update table based on cleared cards and mark all references to the other spaces.
- void UpdateAndMarkReferences(MarkObjectCallback* callback, void* arg)
+ void UpdateAndMarkReferences(MarkHeapReferenceCallback* callback, void* arg)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
@@ -142,7 +142,7 @@ class ModUnionTableCardCache : public ModUnionTable {
void ClearCards();
// Mark all references to the alloc space(s).
- void UpdateAndMarkReferences(MarkObjectCallback* callback, void* arg)
+ void UpdateAndMarkReferences(MarkHeapReferenceCallback* callback, void* arg)
EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/gc/accounting/remembered_set.cc b/runtime/gc/accounting/remembered_set.cc
index a832615..afa5054 100644
--- a/runtime/gc/accounting/remembered_set.cc
+++ b/runtime/gc/accounting/remembered_set.cc
@@ -60,28 +60,24 @@ void RememberedSet::ClearCards() {
class RememberedSetReferenceVisitor {
public:
- RememberedSetReferenceVisitor(MarkObjectCallback* callback, space::ContinuousSpace* target_space,
+ RememberedSetReferenceVisitor(MarkHeapReferenceCallback* callback,
+ space::ContinuousSpace* target_space,
bool* const contains_reference_to_target_space, void* arg)
: callback_(callback), target_space_(target_space), arg_(arg),
contains_reference_to_target_space_(contains_reference_to_target_space) {}
- void operator()(mirror::Object* obj, mirror::Object* ref,
- const MemberOffset& offset, bool /* is_static */) const
+ void operator()(mirror::Object* obj, MemberOffset offset, bool /* is_static */) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (ref != nullptr) {
- if (target_space_->HasAddress(ref)) {
- *contains_reference_to_target_space_ = true;
- mirror::Object* new_ref = callback_(ref, arg_);
- DCHECK(!target_space_->HasAddress(new_ref));
- if (new_ref != ref) {
- obj->SetFieldObjectWithoutWriteBarrier<false>(offset, new_ref, false);
- }
- }
+ mirror::HeapReference<mirror::Object>* ref_ptr = obj->GetFieldObjectReferenceAddr(offset);
+ if (target_space_->HasAddress(ref_ptr->AsMirrorPtr())) {
+ *contains_reference_to_target_space_ = true;
+ callback_(ref_ptr, arg_);
+ DCHECK(!target_space_->HasAddress(ref_ptr->AsMirrorPtr()));
}
}
private:
- MarkObjectCallback* const callback_;
+ MarkHeapReferenceCallback* const callback_;
space::ContinuousSpace* const target_space_;
void* const arg_;
bool* const contains_reference_to_target_space_;
@@ -89,27 +85,27 @@ class RememberedSetReferenceVisitor {
class RememberedSetObjectVisitor {
public:
- RememberedSetObjectVisitor(MarkObjectCallback* callback, space::ContinuousSpace* target_space,
+ RememberedSetObjectVisitor(MarkHeapReferenceCallback* callback,
+ space::ContinuousSpace* target_space,
bool* const contains_reference_to_target_space, void* arg)
: callback_(callback), target_space_(target_space), arg_(arg),
contains_reference_to_target_space_(contains_reference_to_target_space) {}
void operator()(mirror::Object* obj) const EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(obj != NULL);
RememberedSetReferenceVisitor ref_visitor(callback_, target_space_,
contains_reference_to_target_space_, arg_);
- collector::MarkSweep::VisitObjectReferences<kMovingClasses>(obj, ref_visitor);
+ obj->VisitReferences<kMovingClasses>(ref_visitor);
}
private:
- MarkObjectCallback* const callback_;
+ MarkHeapReferenceCallback* const callback_;
space::ContinuousSpace* const target_space_;
void* const arg_;
bool* const contains_reference_to_target_space_;
};
-void RememberedSet::UpdateAndMarkReferences(MarkObjectCallback* callback,
+void RememberedSet::UpdateAndMarkReferences(MarkHeapReferenceCallback* callback,
space::ContinuousSpace* target_space, void* arg) {
CardTable* card_table = heap_->GetCardTable();
bool contains_reference_to_target_space = false;
diff --git a/runtime/gc/accounting/remembered_set.h b/runtime/gc/accounting/remembered_set.h
index 92feeb1..4ed20dd 100644
--- a/runtime/gc/accounting/remembered_set.h
+++ b/runtime/gc/accounting/remembered_set.h
@@ -52,7 +52,7 @@ class RememberedSet {
void ClearCards();
// Mark through all references to the target space.
- void UpdateAndMarkReferences(MarkObjectCallback* callback,
+ void UpdateAndMarkReferences(MarkHeapReferenceCallback* callback,
space::ContinuousSpace* target_space, void* arg)
EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
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);
}
}
diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc
index bfef438..8abf5e2 100644
--- a/runtime/gc/collector/mark_sweep.cc
+++ b/runtime/gc/collector/mark_sweep.cc
@@ -279,7 +279,7 @@ void MarkSweep::UpdateAndMarkModUnion() {
TimingLogger::ScopedSplit split(name, &timings_);
accounting::ModUnionTable* mod_union_table = heap_->FindModUnionTableFromSpace(space);
CHECK(mod_union_table != nullptr);
- mod_union_table->UpdateAndMarkReferences(MarkObjectCallback, this);
+ mod_union_table->UpdateAndMarkReferences(MarkHeapReferenceCallback, this);
}
}
}
@@ -410,6 +410,10 @@ mirror::Object* MarkSweep::MarkObjectCallback(mirror::Object* obj, void* arg) {
return obj;
}
+void MarkSweep::MarkHeapReferenceCallback(mirror::HeapReference<mirror::Object>* ref, void* arg) {
+ reinterpret_cast<MarkSweep*>(arg)->MarkObject(ref->AsMirrorPtr());
+}
+
inline void MarkSweep::UnMarkObjectNonNull(const Object* obj) {
DCHECK(!immune_region_.ContainsObject(obj));
if (kUseBrooksPointer) {
@@ -612,8 +616,8 @@ class ScanObjectVisitor {
explicit ScanObjectVisitor(MarkSweep* const mark_sweep) ALWAYS_INLINE
: mark_sweep_(mark_sweep) {}
- // TODO: Fixme when anotatalysis works with visitors.
- void operator()(Object* obj) const ALWAYS_INLINE NO_THREAD_SAFETY_ANALYSIS {
+ void operator()(Object* obj) const ALWAYS_INLINE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) {
if (kCheckLocks) {
Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
Locks::heap_bitmap_lock_->AssertExclusiveHeld(Thread::Current());
@@ -625,6 +629,21 @@ class ScanObjectVisitor {
MarkSweep* const mark_sweep_;
};
+class DelayReferenceReferentVisitor {
+ public:
+ explicit DelayReferenceReferentVisitor(MarkSweep* collector) : collector_(collector) {
+ }
+
+ void operator()(mirror::Class* klass, mirror::Reference* ref) const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) {
+ collector_->DelayReferenceReferent(klass, ref);
+ }
+
+ private:
+ MarkSweep* const collector_;
+};
+
template <bool kUseFinger = false>
class MarkStackTask : public Task {
public:
@@ -647,27 +666,44 @@ class MarkStackTask : public Task {
static const size_t kMaxSize = 1 * KB;
protected:
+ class MarkObjectParallelVisitor {
+ public:
+ explicit MarkObjectParallelVisitor(MarkStackTask<kUseFinger>* chunk_task,
+ MarkSweep* mark_sweep) ALWAYS_INLINE
+ : chunk_task_(chunk_task), mark_sweep_(mark_sweep) {}
+
+ void operator()(Object* obj, MemberOffset offset, bool /* static */) const ALWAYS_INLINE
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ mirror::Object* ref = obj->GetFieldObject<mirror::Object>(offset, false);
+ if (ref != nullptr && mark_sweep_->MarkObjectParallel(ref)) {
+ if (kUseFinger) {
+ android_memory_barrier();
+ if (reinterpret_cast<uintptr_t>(ref) >=
+ static_cast<uintptr_t>(mark_sweep_->atomic_finger_)) {
+ return;
+ }
+ }
+ chunk_task_->MarkStackPush(ref);
+ }
+ }
+
+ private:
+ MarkStackTask<kUseFinger>* const chunk_task_;
+ MarkSweep* const mark_sweep_;
+ };
+
class ScanObjectParallelVisitor {
public:
explicit ScanObjectParallelVisitor(MarkStackTask<kUseFinger>* chunk_task) ALWAYS_INLINE
: chunk_task_(chunk_task) {}
- void operator()(Object* obj) const {
- MarkSweep* mark_sweep = chunk_task_->mark_sweep_;
- mark_sweep->ScanObjectVisit(obj,
- [mark_sweep, this](Object* /* obj */, Object* ref, const MemberOffset& /* offset */,
- bool /* is_static */) ALWAYS_INLINE_LAMBDA {
- if (ref != nullptr && mark_sweep->MarkObjectParallel(ref)) {
- if (kUseFinger) {
- android_memory_barrier();
- if (reinterpret_cast<uintptr_t>(ref) >=
- static_cast<uintptr_t>(mark_sweep->atomic_finger_)) {
- return;
- }
- }
- chunk_task_->MarkStackPush(ref);
- }
- });
+ // No thread safety analysis since multiple threads will use this visitor.
+ void operator()(Object* obj) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) {
+ MarkSweep* const mark_sweep = chunk_task_->mark_sweep_;
+ MarkObjectParallelVisitor mark_visitor(chunk_task_, mark_sweep);
+ DelayReferenceReferentVisitor ref_visitor(mark_sweep);
+ mark_sweep->ScanObjectVisit(obj, mark_visitor, ref_visitor);
}
private:
@@ -707,7 +743,8 @@ class MarkStackTask : public Task {
}
// Scans all of the objects
- virtual void Run(Thread* self) {
+ virtual void Run(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) {
ScanObjectParallelVisitor visitor(this);
// TODO: Tune this.
static const size_t kFifoSize = 4;
@@ -1197,30 +1234,29 @@ void MarkSweep::SweepLargeObjects(bool swap_bitmaps) {
GetHeap()->RecordFree(freed_objects, freed_bytes);
}
-// Process the "referent" field in a java.lang.ref.Reference. If the
-// referent has not yet been marked, put it on the appropriate list in
-// the heap for later processing.
-void MarkSweep::DelayReferenceReferent(mirror::Class* klass, Object* obj) {
+// Process the "referent" field in a java.lang.ref.Reference. If the referent has not yet been
+// marked, put it on the appropriate list in the heap for later processing.
+void MarkSweep::DelayReferenceReferent(mirror::Class* klass, mirror::Reference* ref) {
DCHECK(klass != nullptr);
if (kCountJavaLangRefs) {
++reference_count_;
}
- heap_->DelayReferenceReferent(klass, obj->AsReference(), IsMarkedCallback, this);
+ heap_->DelayReferenceReferent(klass, ref, IsMarkedCallback, this);
}
class MarkObjectVisitor {
public:
- explicit MarkObjectVisitor(MarkSweep* const mark_sweep) ALWAYS_INLINE : mark_sweep_(mark_sweep) {}
+ explicit MarkObjectVisitor(MarkSweep* const mark_sweep) ALWAYS_INLINE : mark_sweep_(mark_sweep) {
+ }
- // TODO: Fixme when anotatalysis works with visitors.
- void operator()(Object* /* obj */, Object* ref, const MemberOffset& /* offset */,
- bool /* is_static */) const ALWAYS_INLINE
- NO_THREAD_SAFETY_ANALYSIS {
+ void operator()(Object* obj, MemberOffset offset, bool /* is_static */) const
+ ALWAYS_INLINE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) {
if (kCheckLocks) {
Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
Locks::heap_bitmap_lock_->AssertExclusiveHeld(Thread::Current());
}
- mark_sweep_->MarkObject(ref);
+ mark_sweep_->MarkObject(obj->GetFieldObject<mirror::Object>(offset, false));
}
private:
@@ -1230,8 +1266,9 @@ class MarkObjectVisitor {
// Scans an object reference. Determines the type of the reference
// and dispatches to a specialized scanning routine.
void MarkSweep::ScanObject(Object* obj) {
- MarkObjectVisitor visitor(this);
- ScanObjectVisit(obj, visitor);
+ MarkObjectVisitor mark_visitor(this);
+ DelayReferenceReferentVisitor ref_visitor(this);
+ ScanObjectVisit(obj, mark_visitor, ref_visitor);
}
void MarkSweep::ProcessMarkStackPausedCallback(void* arg) {
diff --git a/runtime/gc/collector/mark_sweep.h b/runtime/gc/collector/mark_sweep.h
index 59f8e28..84b775a 100644
--- a/runtime/gc/collector/mark_sweep.h
+++ b/runtime/gc/collector/mark_sweep.h
@@ -33,6 +33,7 @@ namespace mirror {
class Class;
class Object;
template<class T> class ObjectArray;
+ class Reference;
} // namespace mirror
class StackVisitor;
@@ -162,10 +163,12 @@ class MarkSweep : public GarbageCollector {
EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- // TODO: enable thread safety analysis when in use by multiple worker threads.
- template <typename MarkVisitor>
- void ScanObjectVisit(mirror::Object* obj, const MarkVisitor& visitor)
- NO_THREAD_SAFETY_ANALYSIS;
+ // No thread safety analysis due to lambdas.
+ template<typename MarkVisitor, typename ReferenceVisitor>
+ void ScanObjectVisit(mirror::Object* obj, const MarkVisitor& visitor,
+ const ReferenceVisitor& ref_visitor)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
void SweepSystemWeaks()
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::heap_bitmap_lock_);
@@ -180,14 +183,14 @@ class MarkSweep : public GarbageCollector {
void VerifyIsLive(const mirror::Object* obj)
SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
- template <bool kVisitClass, typename Visitor>
- static void VisitObjectReferences(mirror::Object* obj, const Visitor& visitor)
- SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_);
-
static mirror::Object* MarkObjectCallback(mirror::Object* obj, void* arg)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
+ static void MarkHeapReferenceCallback(mirror::HeapReference<mirror::Object>* ref, void* arg)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
+
static void MarkRootCallback(mirror::Object** root, void* arg, uint32_t thread_id,
RootType root_type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
@@ -214,6 +217,10 @@ class MarkSweep : public GarbageCollector {
return *gc_barrier_;
}
+ // Schedules an unmarked object for reference processing.
+ void DelayReferenceReferent(mirror::Class* klass, mirror::Reference* reference)
+ SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_);
+
protected:
// Returns true if the object has its bit set in the mark bitmap.
bool IsMarked(const mirror::Object* object) const;
@@ -269,32 +276,6 @@ class MarkSweep : public GarbageCollector {
void VerifyRoot(const mirror::Object* root, size_t vreg, const StackVisitor* visitor)
NO_THREAD_SAFETY_ANALYSIS;
- template <bool kVisitClass, typename Visitor>
- static void VisitInstanceFieldsReferences(mirror::Class* klass, mirror::Object* obj,
- const Visitor& visitor)
- SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_);
-
- // Visit the header, static field references, and interface pointers of a class object.
- template <bool kVisitClass, typename Visitor>
- static void VisitClassReferences(mirror::Class* klass, mirror::Object* obj,
- const Visitor& visitor)
- SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_);
-
- template <bool kVisitClass, typename Visitor>
- static void VisitStaticFieldsReferences(mirror::Class* klass, const Visitor& visitor)
- SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_);
-
- template <bool kVisitClass, typename Visitor>
- static void VisitFieldsReferences(mirror::Object* obj, uint32_t ref_offsets, bool is_static,
- const Visitor& visitor)
- SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_);
-
- // Visit all of the references in an object array.
- template <typename Visitor>
- static void VisitObjectArrayReferences(mirror::ObjectArray<mirror::Object>* array,
- const Visitor& visitor)
- SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_);
-
// Push a single reference on a mark stack.
void PushOnMarkStack(mirror::Object* obj);
@@ -303,10 +284,6 @@ class MarkSweep : public GarbageCollector {
EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- // Schedules an unmarked object for reference processing.
- void DelayReferenceReferent(mirror::Class* klass, mirror::Object* reference)
- SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_);
-
// Recursively blackens objects on the mark stack.
void ProcessMarkStack(bool paused)
EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
@@ -316,17 +293,6 @@ class MarkSweep : public GarbageCollector {
EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void EnqueueFinalizerReferences(mirror::Object** ref)
- EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- void PreserveSomeSoftReferences(mirror::Object** ref)
- EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- void ClearWhiteReferences(mirror::Object** list)
- SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_);
-
// Used to get around thread safety annotations. The call is from MarkingPhase and is guarded by
// IsExclusiveHeld.
void RevokeAllThreadLocalAllocationStacks(Thread* self) NO_THREAD_SAFETY_ANALYSIS;
diff --git a/runtime/gc/collector/semi_space.cc b/runtime/gc/collector/semi_space.cc
index b6591fc..5faa3a1 100644
--- a/runtime/gc/collector/semi_space.cc
+++ b/runtime/gc/collector/semi_space.cc
@@ -97,18 +97,13 @@ void SemiSpace::BindBitmaps() {
SemiSpace::SemiSpace(Heap* heap, bool generational, const std::string& name_prefix)
: GarbageCollector(heap,
name_prefix + (name_prefix.empty() ? "" : " ") + "marksweep + semispace"),
- mark_stack_(nullptr),
- is_large_object_space_immune_(false),
to_space_(nullptr),
- to_space_live_bitmap_(nullptr),
from_space_(nullptr),
- self_(nullptr),
generational_(generational),
last_gc_to_space_end_(nullptr),
bytes_promoted_(0),
whole_heap_collection_(true),
- whole_heap_collection_interval_counter_(0),
- saved_bytes_(0) {
+ whole_heap_collection_interval_counter_(0) {
}
void SemiSpace::InitializePhase() {
@@ -214,7 +209,7 @@ void SemiSpace::UpdateAndMarkModUnion() {
space->IsZygoteSpace() ? "UpdateAndMarkZygoteModUnionTable" :
"UpdateAndMarkImageModUnionTable",
&timings_);
- table->UpdateAndMarkReferences(MarkObjectCallback, this);
+ table->UpdateAndMarkReferences(MarkHeapReferenceCallback, this);
} else if (heap_->FindRememberedSetFromSpace(space) != nullptr) {
DCHECK(kUseRememberedSet);
// If a bump pointer space only collection, the non-moving
@@ -246,7 +241,8 @@ void SemiSpace::UpdateAndMarkModUnion() {
class SemiSpaceScanObjectVisitor {
public:
explicit SemiSpaceScanObjectVisitor(SemiSpace* ss) : semi_space_(ss) {}
- void operator()(Object* obj) const NO_THREAD_SAFETY_ANALYSIS {
+ void operator()(Object* obj) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) {
// TODO: fix NO_THREAD_SAFETY_ANALYSIS. ScanObject() requires an
// exclusive lock on the mutator lock, but
// SpaceBitmap::VisitMarkedRange() only requires the shared lock.
@@ -263,22 +259,21 @@ class SemiSpaceVerifyNoFromSpaceReferencesVisitor {
explicit SemiSpaceVerifyNoFromSpaceReferencesVisitor(space::ContinuousMemMapAllocSpace* from_space) :
from_space_(from_space) {}
- void operator()(Object* obj, Object* ref, const MemberOffset& offset, bool /* is_static */)
- const ALWAYS_INLINE {
+ void operator()(Object* obj, MemberOffset offset, bool /* is_static */) const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE {
+ mirror::Object* ref = obj->GetFieldObject<mirror::Object>(offset, false);
if (from_space_->HasAddress(ref)) {
Runtime::Current()->GetHeap()->DumpObject(LOG(INFO), obj);
}
- DCHECK(!from_space_->HasAddress(ref));
}
private:
space::ContinuousMemMapAllocSpace* from_space_;
};
void SemiSpace::VerifyNoFromSpaceReferences(Object* obj) {
- DCHECK(obj != NULL);
DCHECK(!from_space_->HasAddress(obj)) << "Scanning object " << obj << " in from space";
SemiSpaceVerifyNoFromSpaceReferencesVisitor visitor(from_space_);
- MarkSweep::VisitObjectReferences<kMovingClasses>(obj, visitor);
+ obj->VisitReferences<kMovingClasses>(visitor);
}
class SemiSpaceVerifyNoFromSpaceReferencesObjectVisitor {
@@ -313,7 +308,7 @@ void SemiSpace::MarkReachableObjects() {
accounting::RememberedSet* rem_set = heap_->FindRememberedSetFromSpace(space);
if (kUseRememberedSet) {
DCHECK(rem_set != nullptr);
- rem_set->UpdateAndMarkReferences(MarkObjectCallback, from_space_, this);
+ rem_set->UpdateAndMarkReferences(MarkHeapReferenceCallback, from_space_, this);
if (kIsDebugBuild) {
// Verify that there are no from-space references that
// remain in the space, that is, the remembered set (and the
@@ -475,9 +470,9 @@ static inline size_t CopyAvoidingDirtyingPages(void* dest, const void* src, size
memcpy(dest, src, page_remain);
byte_src += page_remain;
byte_dest += page_remain;
- CHECK_ALIGNED(reinterpret_cast<uintptr_t>(byte_dest), kPageSize);
- CHECK_ALIGNED(reinterpret_cast<uintptr_t>(byte_dest), sizeof(uintptr_t));
- CHECK_ALIGNED(reinterpret_cast<uintptr_t>(byte_src), sizeof(uintptr_t));
+ DCHECK_ALIGNED(reinterpret_cast<uintptr_t>(byte_dest), kPageSize);
+ DCHECK_ALIGNED(reinterpret_cast<uintptr_t>(byte_dest), sizeof(uintptr_t));
+ DCHECK_ALIGNED(reinterpret_cast<uintptr_t>(byte_src), sizeof(uintptr_t));
while (byte_src + kPageSize < limit) {
bool all_zero = true;
uintptr_t* word_dest = reinterpret_cast<uintptr_t*>(byte_dest);
@@ -582,17 +577,18 @@ mirror::Object* SemiSpace::MarkNonForwardedObject(mirror::Object* obj) {
// Used to mark and copy objects. Any newly-marked objects who are in the from space get moved to
// the to-space and have their forward address updated. Objects which have been newly marked are
// pushed on the mark stack.
-Object* SemiSpace::MarkObject(Object* obj) {
+void SemiSpace::MarkObject(mirror::HeapReference<Object>* obj_ptr) {
+ Object* obj = obj_ptr->AsMirrorPtr();
+ if (obj == nullptr) {
+ return;
+ }
if (kUseBrooksPointer) {
// Verify all the objects have the correct forward pointer installed.
- if (obj != nullptr) {
- obj->AssertSelfBrooksPointer();
- }
+ obj->AssertSelfBrooksPointer();
}
- Object* forward_address = obj;
- if (obj != nullptr && !immune_region_.ContainsObject(obj)) {
+ if (!immune_region_.ContainsObject(obj)) {
if (from_space_->HasAddress(obj)) {
- forward_address = GetForwardingAddressInFromSpace(obj);
+ mirror::Object* forward_address = GetForwardingAddressInFromSpace(obj);
// If the object has already been moved, return the new forward address.
if (forward_address == nullptr) {
forward_address = MarkNonForwardedObject(obj);
@@ -604,9 +600,10 @@ Object* SemiSpace::MarkObject(Object* obj) {
// Push the object onto the mark stack for later processing.
MarkStackPush(forward_address);
}
- // TODO: Do we need this if in the else statement?
+ obj_ptr->Assign(forward_address);
} else {
- accounting::SpaceBitmap* object_bitmap = heap_->GetMarkBitmap()->GetContinuousSpaceBitmap(obj);
+ accounting::SpaceBitmap* object_bitmap =
+ heap_->GetMarkBitmap()->GetContinuousSpaceBitmap(obj);
if (LIKELY(object_bitmap != nullptr)) {
if (generational_) {
// If a bump pointer space only collection, we should not
@@ -615,9 +612,8 @@ Object* SemiSpace::MarkObject(Object* obj) {
// the non-moving space is added to the immune space.
DCHECK(whole_heap_collection_);
}
- // This object was not previously marked.
- if (!object_bitmap->Test(obj)) {
- object_bitmap->Set(obj);
+ if (!object_bitmap->Set(obj)) {
+ // This object was not previously marked.
MarkStackPush(obj);
}
} else {
@@ -628,25 +624,30 @@ Object* SemiSpace::MarkObject(Object* obj) {
}
}
}
- return forward_address;
}
void SemiSpace::ProcessMarkStackCallback(void* arg) {
- DCHECK(arg != nullptr);
reinterpret_cast<SemiSpace*>(arg)->ProcessMarkStack();
}
mirror::Object* SemiSpace::MarkObjectCallback(mirror::Object* root, void* arg) {
- DCHECK(root != nullptr);
- DCHECK(arg != nullptr);
- return reinterpret_cast<SemiSpace*>(arg)->MarkObject(root);
+ auto ref = mirror::HeapReference<mirror::Object>::FromMirrorPtr(root);
+ reinterpret_cast<SemiSpace*>(arg)->MarkObject(&ref);
+ return ref.AsMirrorPtr();
+}
+
+void SemiSpace::MarkHeapReferenceCallback(mirror::HeapReference<mirror::Object>* obj_ptr,
+ void* arg) {
+ reinterpret_cast<SemiSpace*>(arg)->MarkObject(obj_ptr);
}
void SemiSpace::MarkRootCallback(Object** root, void* arg, uint32_t /*thread_id*/,
RootType /*root_type*/) {
- DCHECK(root != nullptr);
- DCHECK(arg != nullptr);
- *root = reinterpret_cast<SemiSpace*>(arg)->MarkObject(*root);
+ auto ref = mirror::HeapReference<mirror::Object>::FromMirrorPtr(*root);
+ reinterpret_cast<SemiSpace*>(arg)->MarkObject(&ref);
+ if (*root != ref.AsMirrorPtr()) {
+ *root = ref.AsMirrorPtr();
+ }
}
// Marks all objects in the root set.
@@ -708,42 +709,35 @@ void SemiSpace::SweepLargeObjects(bool swap_bitmaps) {
// Process the "referent" field in a java.lang.ref.Reference. If the referent has not yet been
// marked, put it on the appropriate list in the heap for later processing.
-void SemiSpace::DelayReferenceReferent(mirror::Class* klass, Object* obj) {
- heap_->DelayReferenceReferent(klass, obj->AsReference(), MarkedForwardingAddressCallback, this);
+void SemiSpace::DelayReferenceReferent(mirror::Class* klass, mirror::Reference* reference) {
+ heap_->DelayReferenceReferent(klass, reference, MarkedForwardingAddressCallback, this);
}
class SemiSpaceMarkObjectVisitor {
public:
- explicit SemiSpaceMarkObjectVisitor(SemiSpace* semi_space) : semi_space_(semi_space) {
- }
-
- void operator()(Object* obj, Object* ref, const MemberOffset& offset, bool /* is_static */)
- const ALWAYS_INLINE NO_THREAD_SAFETY_ANALYSIS /* EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) */ {
- mirror::Object* new_address = semi_space_->MarkObject(ref);
- if (new_address != ref) {
- DCHECK(new_address != nullptr);
- // Don't need to mark the card since we updating the object address and not changing the
- // actual objects its pointing to. Using SetFieldObjectWithoutWriteBarrier is better in this
- // case since it does not dirty cards and use additional memory.
- // Since we do not change the actual object, we can safely use non-transactional mode. Also
- // disable check as we could run inside a transaction.
- obj->SetFieldObjectWithoutWriteBarrier<false, false, kVerifyNone>(offset, new_address, false);
- }
+ explicit SemiSpaceMarkObjectVisitor(SemiSpace* collector) : collector_(collector) {
}
+
+ void operator()(Object* obj, MemberOffset offset, bool /* is_static */) const ALWAYS_INLINE
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::heap_bitmap_lock_) {
+ collector_->MarkObject(obj->GetFieldObjectReferenceAddr(offset));
+ }
+
+ void operator()(mirror::Class* klass, mirror::Reference* ref) const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) {
+ collector_->DelayReferenceReferent(klass, ref);
+ }
+
private:
- SemiSpace* const semi_space_;
+ SemiSpace* const collector_;
};
// Visit all of the references of an object and update.
void SemiSpace::ScanObject(Object* obj) {
- DCHECK(obj != NULL);
DCHECK(!from_space_->HasAddress(obj)) << "Scanning object " << obj << " in from space";
SemiSpaceMarkObjectVisitor visitor(this);
- MarkSweep::VisitObjectReferences<kMovingClasses>(obj, visitor);
- mirror::Class* klass = obj->GetClass<kVerifyNone>();
- if (UNLIKELY(klass->IsReferenceClass<kVerifyNone>())) {
- DelayReferenceReferent(klass, obj);
- }
+ obj->VisitReferences<kMovingClasses>(visitor, visitor);
}
// Scan anything that's on the mark stack.
diff --git a/runtime/gc/collector/semi_space.h b/runtime/gc/collector/semi_space.h
index 0d77f29..523c2ab 100644
--- a/runtime/gc/collector/semi_space.h
+++ b/runtime/gc/collector/semi_space.h
@@ -98,11 +98,13 @@ class SemiSpace : public GarbageCollector {
void FindDefaultMarkBitmap();
// Returns the new address of the object.
- mirror::Object* MarkObject(mirror::Object* object)
- EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_);
+ void MarkObject(mirror::HeapReference<mirror::Object>* obj_ptr)
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void ScanObject(mirror::Object* obj)
- EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_);
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void VerifyNoFromSpaceReferences(mirror::Object* obj)
SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_);
@@ -138,11 +140,19 @@ class SemiSpace : public GarbageCollector {
static mirror::Object* MarkObjectCallback(mirror::Object* root, void* arg)
EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_);
+ static void MarkHeapReferenceCallback(mirror::HeapReference<mirror::Object>* obj_ptr, void* arg)
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_);
+
static void ProcessMarkStackCallback(void* arg)
EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::heap_bitmap_lock_);
virtual mirror::Object* MarkNonForwardedObject(mirror::Object* obj)
- EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_);
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ // Schedules an unmarked object for reference processing.
+ void DelayReferenceReferent(mirror::Class* klass, mirror::Reference* reference)
+ SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_);
protected:
// Returns null if the object is not marked, otherwise returns the forwarding address (same as
@@ -158,7 +168,8 @@ class SemiSpace : public GarbageCollector {
// Marks or unmarks a large object based on whether or not set is true. If set is true, then we
// mark, otherwise we unmark.
bool MarkLargeObject(const mirror::Object* obj)
- EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::heap_bitmap_lock_);
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Expand mark stack to 2x its current size.
void ResizeMarkStack(size_t new_size);
@@ -173,10 +184,6 @@ class SemiSpace : public GarbageCollector {
EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- // Schedules an unmarked object for reference processing.
- void DelayReferenceReferent(mirror::Class* klass, mirror::Object* reference)
- SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_);
-
// Recursively blackens objects on the mark stack.
void ProcessMarkStack()
EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::heap_bitmap_lock_);
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 11c0f71..6c3ae5e 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -1018,20 +1018,20 @@ bool Heap::IsLiveObjectLocked(mirror::Object* obj, bool search_allocation_stack,
}
if (search_allocation_stack) {
if (sorted) {
- if (allocation_stack_->ContainsSorted(const_cast<mirror::Object*>(obj))) {
+ if (allocation_stack_->ContainsSorted(obj)) {
return true;
}
- } else if (allocation_stack_->Contains(const_cast<mirror::Object*>(obj))) {
+ } else if (allocation_stack_->Contains(obj)) {
return true;
}
}
if (search_live_stack) {
if (sorted) {
- if (live_stack_->ContainsSorted(const_cast<mirror::Object*>(obj))) {
+ if (live_stack_->ContainsSorted(obj)) {
return true;
}
- } else if (live_stack_->Contains(const_cast<mirror::Object*>(obj))) {
+ } else if (live_stack_->Contains(obj)) {
return true;
}
}
@@ -1303,14 +1303,15 @@ class ReferringObjectsFinder {
// TODO: Fix lock analysis to not use NO_THREAD_SAFETY_ANALYSIS, requires support for
// annotalysis on visitors.
void operator()(mirror::Object* o) const NO_THREAD_SAFETY_ANALYSIS {
- collector::MarkSweep::VisitObjectReferences<true>(o, *this);
+ o->VisitReferences<true>(*this);
}
// For MarkSweep::VisitObjectReferences.
- void operator()(mirror::Object* referrer, mirror::Object* object,
- const MemberOffset&, bool) const {
- if (object == object_ && (max_count_ == 0 || referring_objects_.size() < max_count_)) {
- referring_objects_.push_back(referrer);
+ void operator()(mirror::Object* obj, MemberOffset offset, bool /* is_static */) const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ mirror::Object* ref = obj->GetFieldObject<mirror::Object>(offset, false);
+ if (ref == object_ && (max_count_ == 0 || referring_objects_.size() < max_count_)) {
+ referring_objects_.push_back(obj);
}
}
@@ -1910,10 +1911,18 @@ class VerifyReferenceVisitor {
return failed_;
}
- // TODO: Fix lock analysis to not use NO_THREAD_SAFETY_ANALYSIS, requires support for smarter
- // analysis on visitors.
- void operator()(mirror::Object* obj, mirror::Object* ref,
- const MemberOffset& offset, bool /* is_static */) const
+ void operator()(mirror::Class* klass, mirror::Reference* ref) const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ this->operator()(ref, mirror::Reference::ReferentOffset(), false);
+ }
+
+ void operator()(mirror::Object* obj, MemberOffset offset, bool /* static */) const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ this->operator()(obj, obj->GetFieldObject<mirror::Object>(offset, false), offset);
+ }
+
+ // TODO: Fix the no thread safety analysis.
+ void operator()(mirror::Object* obj, mirror::Object* ref, MemberOffset offset) const
NO_THREAD_SAFETY_ANALYSIS {
if (ref == nullptr || IsLive(ref)) {
// Verify that the reference is live.
@@ -2014,7 +2023,7 @@ class VerifyReferenceVisitor {
static void VerifyRoots(mirror::Object** root, void* arg, uint32_t /*thread_id*/,
RootType /*root_type*/) {
VerifyReferenceVisitor* visitor = reinterpret_cast<VerifyReferenceVisitor*>(arg);
- (*visitor)(nullptr, *root, MemberOffset(0), true);
+ (*visitor)(nullptr, *root, MemberOffset(0));
}
private:
@@ -2033,11 +2042,7 @@ class VerifyObjectVisitor {
// be live or else how did we find it in the live bitmap?
VerifyReferenceVisitor visitor(heap_);
// The class doesn't count as a reference but we should verify it anyways.
- collector::MarkSweep::VisitObjectReferences<true>(obj, visitor);
- if (obj->IsReferenceInstance()) {
- mirror::Reference* ref = obj->AsReference();
- visitor(obj, ref->GetReferent(), mirror::Reference::ReferentOffset(), false);
- }
+ obj->VisitReferences<true>(visitor, visitor);
failed_ = failed_ || visitor.Failed();
}
@@ -2102,11 +2107,12 @@ class VerifyReferenceCardVisitor {
// TODO: Fix lock analysis to not use NO_THREAD_SAFETY_ANALYSIS, requires support for
// annotalysis on visitors.
- void operator()(mirror::Object* obj, mirror::Object* ref, const MemberOffset& offset,
- bool is_static) const NO_THREAD_SAFETY_ANALYSIS {
+ void operator()(mirror::Object* obj, MemberOffset offset, bool is_static) const
+ NO_THREAD_SAFETY_ANALYSIS {
+ mirror::Object* ref = obj->GetFieldObject<mirror::Object>(offset, false);
// Filter out class references since changing an object's class does not mark the card as dirty.
// Also handles large objects, since the only reference they hold is a class reference.
- if (ref != NULL && !ref->IsClass()) {
+ if (ref != nullptr && !ref->IsClass()) {
accounting::CardTable* card_table = heap_->GetCardTable();
// If the object is not dirty and it is referencing something in the live stack other than
// class, then it must be on a dirty card.
@@ -2118,8 +2124,8 @@ class VerifyReferenceCardVisitor {
// Card should be either kCardDirty if it got re-dirtied after we aged it, or
// kCardDirty - 1 if it didnt get touched since we aged it.
accounting::ObjectStack* live_stack = heap_->live_stack_.get();
- if (live_stack->ContainsSorted(const_cast<mirror::Object*>(ref))) {
- if (live_stack->ContainsSorted(const_cast<mirror::Object*>(obj))) {
+ if (live_stack->ContainsSorted(ref)) {
+ if (live_stack->ContainsSorted(obj)) {
LOG(ERROR) << "Object " << obj << " found in live stack";
}
if (heap_->GetLiveBitmap()->Test(obj)) {
@@ -2173,7 +2179,7 @@ class VerifyLiveStackReferences {
void operator()(mirror::Object* obj) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::heap_bitmap_lock_) {
VerifyReferenceCardVisitor visitor(heap_, const_cast<bool*>(&failed_));
- collector::MarkSweep::VisitObjectReferences<true>(obj, visitor);
+ obj->VisitReferences<true>(visitor);
}
bool Failed() const {
@@ -2282,8 +2288,7 @@ void Heap::ProcessCards(TimingLogger& timings, bool use_rem_sets) {
}
}
-static mirror::Object* IdentityMarkObjectCallback(mirror::Object* obj, void*) {
- return obj;
+static void IdentityMarkHeapReferenceCallback(mirror::HeapReference<mirror::Object>*, void*) {
}
void Heap::PreGcVerification(collector::GarbageCollector* gc) {
@@ -2321,7 +2326,7 @@ void Heap::PreGcVerification(collector::GarbageCollector* gc) {
ReaderMutexLock reader_lock(self, *Locks::heap_bitmap_lock_);
for (const auto& table_pair : mod_union_tables_) {
accounting::ModUnionTable* mod_union_table = table_pair.second;
- mod_union_table->UpdateAndMarkReferences(IdentityMarkObjectCallback, nullptr);
+ mod_union_table->UpdateAndMarkReferences(IdentityMarkHeapReferenceCallback, nullptr);
mod_union_table->Verify();
}
thread_list->ResumeAll();