Make dvmVerifyCardTable more resiliant, and move invocation to start
and end of GC.

Also removes the dependence on HeapBitmap from the .h file.

Change-Id: I2132d0dedfb8fbd07012563d116e808d444038ab
diff --git a/vm/alloc/CardTable.c b/vm/alloc/CardTable.c
index 1537f7c..45fc1d4 100644
--- a/vm/alloc/CardTable.c
+++ b/vm/alloc/CardTable.c
@@ -202,11 +202,39 @@
 }
 
 /*
- * dvmAbort if a clean, immune Object in the bitmap contains a pointer
- * to a threatened Object.
+ * dvmAbort if any clean object in the Zygote heap contains a
+ * reference to the application heap, or if the immune limit is not as
+ * expected.
  */
-void dvmVerifyCardTable(HeapBitmap *bitmap, const char *immuneLimit)
+void dvmVerifyCardTable(void)
 {
-    dvmHeapBitmapWalk(bitmap, crossGenCheckCallback, (void *)immuneLimit);
+    HeapBitmap markBits[HEAP_SOURCE_MAX_HEAP_COUNT];
+    HeapBitmap liveBits[HEAP_SOURCE_MAX_HEAP_COUNT];
+    size_t numBitmaps;
+    void *immuneLimit;
+    numBitmaps = dvmHeapSourceGetNumHeaps();
+    if (numBitmaps < 2) {
+        return;
+    }
+    if (numBitmaps > 2) {
+        LOGE("More heaps than expected.");
+        dvmAbort();
+    }
+    immuneLimit = dvmHeapSourceGetImmuneLimit(GC_PARTIAL);
+    dvmHeapSourceGetObjectBitmaps(liveBits, markBits, numBitmaps);
+    if (markBits[0].base <= markBits[1].base) {
+        LOGE("Heaps are not in the expected order.");
+        dvmAbort();
+    }
+    if (markBits[0].base < (uintptr_t)immuneLimit ||
+        markBits[0].max < (uintptr_t)immuneLimit) {
+        LOGE("Application heap should not be immune.");
+        dvmAbort();
+    }
+    if (markBits[1].base >= (uintptr_t)immuneLimit ||
+        markBits[1].max >= (uintptr_t)immuneLimit) {
+        LOGE("Zygote heap should not be threatened.");
+        dvmAbort();
+    }
+    dvmHeapBitmapWalk(&markBits[1], crossGenCheckCallback, immuneLimit);
 }
-
diff --git a/vm/alloc/CardTable.h b/vm/alloc/CardTable.h
index 86995b6..4c4bee6 100644
--- a/vm/alloc/CardTable.h
+++ b/vm/alloc/CardTable.h
@@ -32,8 +32,6 @@
 #define GC_CARD_CLEAN 0
 #define GC_CARD_DIRTY 0x70
 
-struct HeapBitmap;
-
 /*
  * Initializes the card table; must be called before any other
  * dvmCardTable*() functions.
@@ -62,10 +60,11 @@
 void dvmMarkCard(const void *addr);
 
 /*
- * dvmAbort if a clean, immune Object in the bitmap contains a pointer
- * to a threatened Object.
+ * dvmAbort if any clean object in the Zygote heap contains a
+ * reference to the application heap, or if the immune limit is not as
+ * expected.
  */
-void dvmVerifyCardTable(struct HeapBitmap *bitmap, const char *immuneLimit);
+void dvmVerifyCardTable(void);
 
 /* TODO: Clearing, querying, and iterating over the card table. */
 
diff --git a/vm/alloc/Heap.c b/vm/alloc/Heap.c
index b94f106..e3cc9d6 100644
--- a/vm/alloc/Heap.c
+++ b/vm/alloc/Heap.c
@@ -697,6 +697,9 @@
         LOGV_HEAP("Verifying heap before GC");
         verifyHeap();
     }
+    if (gDvm.verifyCardTable) {
+        dvmVerifyCardTable();
+    }
 
 #ifdef WITH_PROFILER
     dvmMethodTraceGCBegin();
@@ -887,6 +890,9 @@
         LOGV_HEAP("Verifying heap after GC");
         verifyHeap();
     }
+    if (gDvm.verifyCardTable) {
+        dvmVerifyCardTable();
+    }
 
     gcHeap->gcRunning = false;
 
diff --git a/vm/alloc/MarkSweep.c b/vm/alloc/MarkSweep.c
index 1ead96c..912be0c 100644
--- a/vm/alloc/MarkSweep.c
+++ b/vm/alloc/MarkSweep.c
@@ -736,9 +736,6 @@
             size_t j = numBitmaps-1-i;
             assert(j == 0 || (markBits[j].base < markBits[j-1].base));
             if (markBits[j].base < (uintptr_t)ctx->immuneLimit) {
-                if (gDvm.verifyCardTable) {
-                    dvmVerifyCardTable(&markBits[j], ctx->immuneLimit);
-                }
                 uintptr_t minAddr = markBits[j].base;
                 uintptr_t maxAddr = markBits[j].base +
                     HB_MAX_OFFSET(&markBits[j]);
@@ -765,9 +762,6 @@
                         }
                     }
                 }
-                if (gDvm.verifyCardTable) {
-                    dvmVerifyCardTable(&markBits[j], ctx->immuneLimit);
-                }
             } else {
                 dvmHeapBitmapWalk(&markBits[j], scanBitmapCallback, ctx);
             }