Added flags to the vm:
-Xgc:[no]preverify
-Xgc:[no]postverify
to run verify routines over the heap pre- and post-gc.

Changed the Verify.h interface. It now publishes an entry point for
verifying a HeapBitmap, rather than the HeapBitmap callback.

Added a dvmHeapSuspendAndVerify to Heap.h for verification outside of
the GC.

Added callbacks before and after GC, under the locks, under flag control.
Processing of properties to produce flags is in a different project,
frameworks/base

Change-Id: I3f3896583fe9e7239bbe2f374d7ed4c5dd5d3e82
diff --git a/vm/Globals.h b/vm/Globals.h
index 681076a..07bf522 100644
--- a/vm/Globals.h
+++ b/vm/Globals.h
@@ -105,8 +105,13 @@
     DexOptimizerMode    dexOptMode;
     DexClassVerifyMode  classVerifyMode;
 
+    /*
+     * GC option flags.
+     */
     bool        preciseGc;
     bool        overwriteFree;
+    bool        preVerify;
+    bool        postVerify;
     bool        generateRegisterMaps;
 
     int         assertionCtrlCount;
diff --git a/vm/Init.c b/vm/Init.c
index 86925a7..41f020a 100644
--- a/vm/Init.c
+++ b/vm/Init.c
@@ -108,6 +108,8 @@
     dvmFprintf(stderr, "  -Xstacktracefile:<filename>\n");
     dvmFprintf(stderr, "  -Xgc:[no]precise\n");
     dvmFprintf(stderr, "  -Xgc:[no]overwritefree\n");
+    dvmFprintf(stderr, "  -Xgc:[no]preverify\n");
+    dvmFprintf(stderr, "  -Xgc:[no]postverify\n");
     dvmFprintf(stderr, "  -Xgenregmap\n");
     dvmFprintf(stderr, "  -Xcheckdexsum\n");
 #if defined(WITH_JIT)
@@ -957,6 +959,14 @@
                 gDvm.overwriteFree = true;
             else if (strcmp(argv[i] + 5, "nooverwritefree") == 0)
                 gDvm.overwriteFree = false;
+            else if (strcmp(argv[i] + 5, "preverify") == 0)
+                gDvm.preVerify = true;
+            else if (strcmp(argv[i] + 5, "nopreverify") == 0)
+                gDvm.preVerify = false;
+            else if (strcmp(argv[i] + 5, "postverify") == 0)
+                gDvm.postVerify = true;
+            else if (strcmp(argv[i] + 5, "nopostverify") == 0)
+                gDvm.postVerify = false;
             else {
                 dvmFprintf(stderr, "Bad value for -Xgc");
                 return -1;
diff --git a/vm/alloc/Heap.c b/vm/alloc/Heap.c
index bece84b..f027c60 100644
--- a/vm/alloc/Heap.c
+++ b/vm/alloc/Heap.c
@@ -17,6 +17,8 @@
  * Garbage-collecting memory allocator.
  */
 #include "Dalvik.h"
+#include "alloc/HeapBitmap.h"
+#include "alloc/Verify.h"
 #include "alloc/HeapTable.h"
 #include "alloc/Heap.h"
 #include "alloc/HeapInternal.h"
@@ -692,6 +694,36 @@
 }
 
 /*
+ * Scan every live object in the heap, holding the locks.
+ */
+static void verifyHeap()
+{
+    // TODO: check the locks.
+    HeapBitmap *liveBits = dvmHeapSourceGetLiveBits();
+    dvmVerifyBitmap(liveBits);
+}
+
+/*
+ * Suspend the VM as for a GC, and assert-fail if any object has any
+ * corrupt references.
+ */
+void dvmHeapSuspendAndVerify()
+{
+    /* Suspend the VM. */
+    dvmSuspendAllThreads(SUSPEND_FOR_VERIFY);
+    dvmLockMutex(&gDvm.heapWorkerLock);
+    dvmAssertHeapWorkerThreadRunning();
+    dvmLockMutex(&gDvm.heapWorkerListLock);
+
+    verifyHeap();
+
+    /* Resume the VM. */
+    dvmUnlockMutex(&gDvm.heapWorkerListLock);
+    dvmUnlockMutex(&gDvm.heapWorkerLock);
+    dvmResumeAllThreads(SUSPEND_FOR_VERIFY);
+}
+
+/*
  * Initiate garbage collection.
  *
  * NOTES:
@@ -800,6 +832,11 @@
      */
     dvmLockMutex(&gDvm.heapWorkerListLock);
 
+    if (gDvm.preVerify) {
+        LOGV_HEAP("Verifying heap before GC");
+        verifyHeap();
+    }
+
 #ifdef WITH_PROFILER
     dvmMethodTraceGCBegin();
 #endif
@@ -1003,10 +1040,16 @@
 #ifdef WITH_PROFILER
     dvmMethodTraceGCEnd();
 #endif
-    LOGV_HEAP("GC finished -- resuming threads\n");
+    LOGV_HEAP("GC finished");
+
+    if (gDvm.postVerify) {
+        LOGV_HEAP("Verifying heap after GC");
+        verifyHeap();
+    }
 
     gcHeap->gcRunning = false;
 
+    LOGV_HEAP("Resuming threads");
     dvmUnlockMutex(&gDvm.heapWorkerListLock);
     dvmUnlockMutex(&gDvm.heapWorkerLock);
 
diff --git a/vm/alloc/Heap.h b/vm/alloc/Heap.h
index e0ddbb8..ed25baf 100644
--- a/vm/alloc/Heap.h
+++ b/vm/alloc/Heap.h
@@ -64,6 +64,12 @@
 };
 
 /*
+ * Suspend the VM as for a GC, and assert-fail if any object has any
+ * corrupt references.
+ */
+void dvmHeapSuspendAndVerify();
+
+/*
  * Run the garbage collector without doing any locking.
  */
 void dvmCollectGarbageInternal(bool collectSoftReferences,
diff --git a/vm/alloc/HeapSource.c b/vm/alloc/HeapSource.c
index 104254b..7b36065 100644
--- a/vm/alloc/HeapSource.c
+++ b/vm/alloc/HeapSource.c
@@ -647,6 +647,16 @@
     }
 }
 
+/*
+ * Get the bitmap representing all live objects.
+ */
+HeapBitmap *dvmHeapSourceGetLiveBits()
+{
+    HS_BOILERPLATE();
+
+    return &gHs->objBits;
+}
+
 void dvmHeapSourceSwapBitmaps(void)
 {
     HeapBitmap tmp;
@@ -882,7 +892,6 @@
 
     if (dvmHeapBitmapCoversAddress(&gHs->objBits, ptr)) {
         return dvmHeapBitmapIsObjectBitSet(&gHs->objBits, ptr) != 0;
-        
     }
     return false;
 }
diff --git a/vm/alloc/HeapSource.h b/vm/alloc/HeapSource.h
index 940b627..221748c 100644
--- a/vm/alloc/HeapSource.h
+++ b/vm/alloc/HeapSource.h
@@ -54,6 +54,11 @@
                                    size_t numHeaps);
 
 /*
+ * Get the bitmap representing all live objects.
+ */
+HeapBitmap *dvmHeapSourceGetLiveBits();
+
+/*
  * Returns the requested value. If the per-heap stats are requested, fill
  * them as well.
  */
diff --git a/vm/alloc/Verify.c b/vm/alloc/Verify.c
index 6da3b1f..20e7b8a 100644
--- a/vm/alloc/Verify.c
+++ b/vm/alloc/Verify.c
@@ -17,6 +17,7 @@
 #include "Dalvik.h"
 #include "alloc/HeapSource.h"
 #include "alloc/Verify.h"
+#include "alloc/HeapBitmap.h"
 
 /* comment everything, of course! */
 #define VERIFY_REFERENCE(x) do {                                \
@@ -173,31 +174,11 @@
 }
 
 /*
- * Verifies the object references in a heap bitmap.  Assumes the heap
- * is locked.
- */
-void dvmVerifyBitmapUnlocked(const HeapBitmap *bitmap)
-{
-    /* TODO: check that locks are held and the VM is suspended. */
-    dvmHeapBitmapWalk(bitmap, verifyBitmapCallback, NULL);
-}
-
-/*
- * Verifies the object references in a heap bitmap.  Suspends the VM
- * for the duration of verification.
+ * Verifies the object references in a heap bitmap. Assumes the VM is
+ * suspended.
  */
 void dvmVerifyBitmap(const HeapBitmap *bitmap)
 {
-    /* Suspend the VM. */
-    dvmSuspendAllThreads(SUSPEND_FOR_VERIFY);
-    dvmLockMutex(&gDvm.heapWorkerLock);
-    dvmAssertHeapWorkerThreadRunning();
-    dvmLockMutex(&gDvm.heapWorkerListLock);
-
-    dvmVerifyBitmapUnlocked(bitmap);
-
-    /* Resume the VM. */
-    dvmUnlockMutex(&gDvm.heapWorkerListLock);
-    dvmUnlockMutex(&gDvm.heapWorkerLock);
-    dvmResumeAllThreads(SUSPEND_FOR_VERIFY);
+    /* TODO: check that locks are held and the VM is suspended. */
+    dvmHeapBitmapWalk(bitmap, verifyBitmapCallback, NULL);
 }
diff --git a/vm/alloc/Verify.h b/vm/alloc/Verify.h
index 2409ad1..a9d86c3 100644
--- a/vm/alloc/Verify.h
+++ b/vm/alloc/Verify.h
@@ -23,14 +23,8 @@
 void dvmVerifyObject(const Object *obj);
 
 /*
- * Verifies the object references in a heap bitmap.  Assumes the heap
- * is locked.
- */
-void dvmVerifyBitmapUnlocked(const HeapBitmap *bitmap);
-
-/*
- * Verifies the object references in a heap bitmap.  Suspends the VM
- * for the duration of verification.
+ * Verifies the object references in a heap bitmap. Assumes the VM is
+ * suspended.
  */
 void dvmVerifyBitmap(const HeapBitmap *bitmap);