ART: Relax heap verification failure count
Changes the atomic fail_count variable used in heap verification to be
a plain variable. It is used thread private state and can be updated
and read with the default C++ memory ordering.
Bug: 31023171
Test: art/test.py --host -j32
Change-Id: I16ad3e138797b9900ecf719ab22c0b2b03e53c33
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 52afb38..247e25c 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -2753,12 +2753,10 @@
// Verify a reference from an object.
class VerifyReferenceVisitor : public SingleRootVisitor {
public:
- VerifyReferenceVisitor(Heap* heap, Atomic<size_t>* fail_count, bool verify_referent)
+ VerifyReferenceVisitor(Thread* self, Heap* heap, size_t* fail_count, bool verify_referent)
REQUIRES_SHARED(Locks::mutator_lock_)
- : heap_(heap), fail_count_(fail_count), verify_referent_(verify_referent) {}
-
- size_t GetFailureCount() const {
- return fail_count_->load(std::memory_order_seq_cst);
+ : self_(self), heap_(heap), fail_count_(fail_count), verify_referent_(verify_referent) {
+ CHECK_EQ(self_, Thread::Current());
}
void operator()(ObjPtr<mirror::Class> klass ATTRIBUTE_UNUSED, ObjPtr<mirror::Reference> ref) const
@@ -2810,8 +2808,10 @@
// Verify that the reference is live.
return true;
}
- if (fail_count_->fetch_add(1, std::memory_order_seq_cst) == 0) {
- // Print message on only on first failure to prevent spam.
+ CHECK_EQ(self_, Thread::Current()); // fail_count_ is private to the calling thread.
+ *fail_count_ += 1;
+ if (*fail_count_ == 1) {
+ // Only print message for the first failure to prevent spam.
LOG(ERROR) << "!!!!!!!!!!!!!!Heap corruption detected!!!!!!!!!!!!!!!!!!!";
}
if (obj != nullptr) {
@@ -2897,38 +2897,41 @@
return false;
}
+ Thread* const self_;
Heap* const heap_;
- Atomic<size_t>* const fail_count_;
+ size_t* const fail_count_;
const bool verify_referent_;
};
// Verify all references within an object, for use with HeapBitmap::Visit.
class VerifyObjectVisitor {
public:
- VerifyObjectVisitor(Heap* heap, Atomic<size_t>* fail_count, bool verify_referent)
- : heap_(heap), fail_count_(fail_count), verify_referent_(verify_referent) {}
+ VerifyObjectVisitor(Thread* self, Heap* heap, size_t* fail_count, bool verify_referent)
+ : self_(self), heap_(heap), fail_count_(fail_count), verify_referent_(verify_referent) {}
void operator()(mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
// Note: we are verifying the references in obj but not obj itself, this is because obj must
// be live or else how did we find it in the live bitmap?
- VerifyReferenceVisitor visitor(heap_, fail_count_, verify_referent_);
+ VerifyReferenceVisitor visitor(self_, heap_, fail_count_, verify_referent_);
// The class doesn't count as a reference but we should verify it anyways.
obj->VisitReferences(visitor, visitor);
}
void VerifyRoots() REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::heap_bitmap_lock_) {
ReaderMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
- VerifyReferenceVisitor visitor(heap_, fail_count_, verify_referent_);
+ VerifyReferenceVisitor visitor(self_, heap_, fail_count_, verify_referent_);
Runtime::Current()->VisitRoots(&visitor);
}
- size_t GetFailureCount() const {
- return fail_count_->load(std::memory_order_seq_cst);
+ uint32_t GetFailureCount() const REQUIRES(Locks::mutator_lock_) {
+ CHECK_EQ(self_, Thread::Current());
+ return *fail_count_;
}
private:
+ Thread* const self_;
Heap* const heap_;
- Atomic<size_t>* const fail_count_;
+ size_t* const fail_count_;
const bool verify_referent_;
};
@@ -2980,8 +2983,8 @@
// Since we sorted the allocation stack content, need to revoke all
// thread-local allocation stacks.
RevokeAllThreadLocalAllocationStacks(self);
- Atomic<size_t> fail_count_(0);
- VerifyObjectVisitor visitor(this, &fail_count_, verify_referents);
+ size_t fail_count = 0;
+ VerifyObjectVisitor visitor(self, this, &fail_count, verify_referents);
// Verify objects in the allocation stack since these will be objects which were:
// 1. Allocated prior to the GC (pre GC verification).
// 2. Allocated during the GC (pre sweep GC verification).