Densely allocate mspaces.  New heaps are started on the page following
the break of the previously allocated heap.  In addition, we shrink
the reported size of the previous object bitmap so it covers only the
committed range of the heap.  We now separately track the size of the
bitmap virtual memory reservation so we may unmap it all at shutdown
time.
diff --git a/vm/alloc/HeapBitmap.c b/vm/alloc/HeapBitmap.c
index 778fd87..e2cf117 100644
--- a/vm/alloc/HeapBitmap.c
+++ b/vm/alloc/HeapBitmap.c
@@ -70,7 +70,7 @@
 
     memset(hb, 0, sizeof(*hb));
     hb->bits = bits;
-    hb->bitsLen = bitsLen;
+    hb->bitsLen = hb->allocLen = bitsLen;
     hb->base = (uintptr_t)base;
     hb->max = hb->base - 1;
 
@@ -126,9 +126,7 @@
     assert(hb != NULL);
 
     if (hb->bits != NULL) {
-        // Re-calculate the size we passed to mmap().
-        size_t allocLen = ALIGN_UP_TO_PAGE_SIZE(hb->bitsLen);
-        munmap((char *)hb->bits, allocLen);
+        munmap((char *)hb->bits, hb->allocLen);
     }
     memset(hb, 0, sizeof(*hb));
 }
diff --git a/vm/alloc/HeapBitmap.h b/vm/alloc/HeapBitmap.h
index 0994600..b9f8164 100644
--- a/vm/alloc/HeapBitmap.h
+++ b/vm/alloc/HeapBitmap.h
@@ -53,10 +53,17 @@
      */
     unsigned long int *bits;
 
-    /* The size of the memory pointed to by bits, in bytes.
+    /* The size of the used memory pointed to by bits, in bytes.  This
+     * value changes when the bitmap is shrunk.
      */
     size_t bitsLen;
 
+    /* The real size of the memory pointed to by bits.  This is the
+     * number of bytes we requested from the allocator and does not
+     * change.
+     */
+    size_t allocLen;
+
     /* The base address, which corresponds to the first bit in
      * the bitmap.
      */
diff --git a/vm/alloc/HeapSource.c b/vm/alloc/HeapSource.c
index 4a31a53..7921591 100644
--- a/vm/alloc/HeapSource.c
+++ b/vm/alloc/HeapSource.c
@@ -337,7 +337,7 @@
         heap.msp = msp;
         heap.absoluteMaxSize = mspAbsoluteMaxSize;
     } else {
-        size_t overhead;
+        size_t diff, overhead;
 
         overhead = oldHeapOverhead(hs, true);
         if (overhead + HEAP_MIN_FREE >= hs->absoluteMaxSize) {
@@ -347,11 +347,14 @@
             return false;
         }
         heap.absoluteMaxSize = hs->absoluteMaxSize - overhead;
-        base = hs->heapBase + ALIGN_UP_TO_PAGE_SIZE(hs->absoluteMaxSize);
+        base = contiguous_mspace_sbrk0(hs->heaps[0].msp);
+        base = (void *)ALIGN_UP_TO_PAGE_SIZE(base);
         heap.msp = createMspace(base, HEAP_MIN_FREE, heap.absoluteMaxSize);
         if (heap.msp == NULL) {
             return false;
         }
+        diff = (size_t)base - hs->heaps[0].objectBitmap.base;
+        hs->heaps[0].objectBitmap.bitsLen = HB_OFFSET_TO_INDEX(diff) * 4;
     }
     if (!dvmHeapBitmapInit(&heap.objectBitmap,
                            (void *)ALIGN_DOWN_TO_PAGE_SIZE(heap.msp),