Added option to allow verification of objects on the stack.
Currently it's defined out by VERIFY_OBJECT_ENABLED. Also made various
fixes to allow heap object verification to work again.
(cherry picked from commit d4983495782be8d54c9c1f0266dc52395b947724)
Change-Id: Icd625e1e0dc240c0ad1d10e2c58c7d5d63fec030
diff --git a/src/heap.cc b/src/heap.cc
index 5a19d28..b12ff2d 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -249,8 +249,6 @@
// make it clear that you can't use locks during heap initialization.
lock_ = new Mutex("Heap lock", kHeapLock);
- Heap::EnableObjectValidation();
-
if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
LOG(INFO) << "Heap() exiting";
}
@@ -318,7 +316,8 @@
#if VERIFY_OBJECT_ENABLED
void Heap::VerifyObject(const Object* obj) {
- if (!verify_objects_) {
+ if (this == NULL || !verify_objects_ || Runtime::Current()->IsShuttingDown() ||
+ Runtime::Current()->GetThreadList()->GetLockOwner() == Thread::Current()->GetTid()) {
return;
}
ScopedHeapLock heap_lock;
diff --git a/src/heap.h b/src/heap.h
index be8c62a..7717871 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -243,6 +243,8 @@
void VerifyObjectLocked(const Object *obj);
+ void VerifyHeapLocked();
+
static void VerificationCallback(Object* obj, void* arg);
Mutex* lock_;
diff --git a/src/heap_bitmap.cc b/src/heap_bitmap.cc
index 21db0e6..d432fa9 100644
--- a/src/heap_bitmap.cc
+++ b/src/heap_bitmap.cc
@@ -87,6 +87,9 @@
void HeapBitmap::Walk(HeapBitmap::Callback* callback, void* arg) {
CHECK(bitmap_begin_ != NULL);
CHECK(callback != NULL);
+ if (heap_end_ < heap_begin_) {
+ return; // Bitmap is empty.
+ }
uintptr_t end = HB_OFFSET_TO_INDEX(heap_end_ - heap_begin_);
for (uintptr_t i = 0; i <= end; ++i) {
word w = bitmap_begin_[i];
diff --git a/src/runtime.cc b/src/runtime.cc
index b340317..1378229 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -642,6 +642,7 @@
options->heap_growth_limit_,
options->heap_maximum_size_,
options->image_);
+ heap_->EnableObjectValidation();
BlockSignals();
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index af8ce22..e76e89f 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -34,6 +34,7 @@
// Be aware the store below may well stomp on an incoming argument
*sp = Runtime::Current()->GetCalleeSaveMethod(type);
self->SetTopOfStack(sp, 0);
+ self->VerifyStack();
}
/*
diff --git a/src/scoped_jni_thread_state.h b/src/scoped_jni_thread_state.h
index 2db04fc..552f5ed 100644
--- a/src/scoped_jni_thread_state.h
+++ b/src/scoped_jni_thread_state.h
@@ -29,6 +29,7 @@
: env_(reinterpret_cast<JNIEnvExt*>(env)) {
self_ = ThreadForEnv(env);
old_thread_state_ = self_->SetState(Thread::kRunnable);
+ self_->VerifyStack();
}
~ScopedJniThreadState() {
diff --git a/src/thread.cc b/src/thread.cc
index 353f94d..f15bfd5 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -1637,7 +1637,7 @@
bool VisitFrame(const Frame& frame, uintptr_t pc) {
Method* m = frame.GetMethod();
if (false) {
- LOG(INFO) << "Visiting stack roots in " << PrettyMethod(m, false)
+ LOG(INFO) << "Visiting stack roots in " << PrettyMethod(m)
<< StringPrintf("@ PC:%04x", m->ToDexPC(pc));
}
// Process register map (which native and callee save methods don't have)
@@ -1728,6 +1728,18 @@
WalkStack(&mapper);
}
+#if VERIFY_OBJECT_ENABLED
+void VerifyObject(const Object* obj, void*) {
+ Runtime::Current()->GetHeap()->VerifyObject(obj);
+}
+
+void Thread::VerifyStack() {
+ Context* context = GetLongJumpContext();
+ ReferenceMapVisitor mapper(context, VerifyObject, NULL);
+ WalkStack(&mapper);
+}
+#endif
+
static const char* kStateNames[] = {
"Terminated",
"Runnable",
diff --git a/src/thread.h b/src/thread.h
index c35d26a..d764ff3 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -324,6 +324,12 @@
void VisitRoots(Heap::RootVisitor* visitor, void* arg);
+#if VERIFY_OBJECT_ENABLED
+ void VerifyStack();
+#else
+ void VerifyStack() {}
+#endif
+
//
// Offsets of various members of native Thread class, used by compiled code.
//