Merge "Pro-active pre-harmonization." into dalvik-dev
diff --git a/dx/src/com/android/dx/command/Main.java b/dx/src/com/android/dx/command/Main.java
index 626cf7a..70a94b0 100644
--- a/dx/src/com/android/dx/command/Main.java
+++ b/dx/src/com/android/dx/command/Main.java
@@ -35,7 +35,8 @@
         "[--dump-width=<n>]\n" +
         "  [--dump-method=<name>[*]] [--verbose-dump] [--no-files] " +
         "[--core-library]\n" +
-        "  [<file>.class | <file>.{zip,jar,apk} | <directory>] ...\n" +
+        "  [--num-threads=<n>] [<file>.class | <file>.{zip,jar,apk} | " +
+        "<directory>] ...\n" +
         "    Convert a set of classfiles into a dex file, optionally " +
         "embedded in a\n" +
         "    jar/zip. Output name must end with one of: .dex .jar " +
diff --git a/vm/Sync.c b/vm/Sync.c
index 67263a6..0a0e65a 100644
--- a/vm/Sync.c
+++ b/vm/Sync.c
@@ -212,11 +212,9 @@
  */
 void dvmDumpMonitorInfo(const char* msg)
 {
-#if QUIET_ZYGOTE_MONITOR
     if (gDvm.zygote) {
         return;
     }
-#endif
 
     int totalCount;
     int liveCount;
diff --git a/vm/Sync.h b/vm/Sync.h
index 1a168b9..e63fb55 100644
--- a/vm/Sync.h
+++ b/vm/Sync.h
@@ -68,8 +68,6 @@
 struct Thread;
 typedef struct Monitor Monitor;
 
-#define QUIET_ZYGOTE_MONITOR 1
-
 /*
  * Initialize a Lock to the proper starting value.
  * This is necessary for thin locking.
diff --git a/vm/alloc/CardTable.c b/vm/alloc/CardTable.c
index 4f90371..fcfe49c 100644
--- a/vm/alloc/CardTable.c
+++ b/vm/alloc/CardTable.c
@@ -290,10 +290,10 @@
  */
 static bool isPushedOnMarkStack(const Object *obj)
 {
-    GcMarkContext *ctx = &gDvm.gcHeap->markContext;
+    GcMarkStack *stack = &gDvm.gcHeap->markContext.stack;
     const Object **ptr;
 
-    for (ptr = ctx->stack.top; ptr != ctx->stack.base; ++ptr) {
+    for (ptr = stack->base; ptr < stack->top; ++ptr) {
         if (*ptr == obj) {
             return true;
         }
diff --git a/vm/alloc/HeapSource.c b/vm/alloc/HeapSource.c
index a18def5..ed58d50 100644
--- a/vm/alloc/HeapSource.c
+++ b/vm/alloc/HeapSource.c
@@ -476,6 +476,38 @@
 }
 
 /*
+ * Create a stack big enough for the worst possible case, where the
+ * heap is perfectly full of the smallest object.
+ * TODO: be better about memory usage; use a smaller stack with
+ *       overflow detection and recovery.
+ */
+static bool allocMarkStack(GcMarkStack *stack, size_t maximumSize)
+{
+    const char *name = "dalvik-mark-stack";
+    void *addr;
+
+    assert(stack != NULL);
+    stack->length = maximumSize * sizeof(Object*) /
+        (sizeof(Object) + HEAP_SOURCE_CHUNK_OVERHEAD);
+    addr = dvmAllocRegion(stack->length, PROT_READ | PROT_WRITE, name);
+    if (addr == NULL) {
+        return false;
+    }
+    stack->base = (const Object **)addr;
+    stack->limit = (const Object **)((char *)addr + stack->length);
+    stack->top = NULL;
+    madvise(stack->base, stack->length, MADV_DONTNEED);
+    return true;
+}
+
+static void freeMarkStack(GcMarkStack *stack)
+{
+    assert(stack != NULL);
+    munmap(stack->base, stack->length);
+    memset(stack, 0, sizeof(*stack));
+}
+
+/*
  * Initializes the heap source; must be called before any other
  * dvmHeapSource*() functions.  Returns a GcHeap structure
  * allocated from the heap source.
@@ -555,7 +587,12 @@
         dvmHeapBitmapDelete(&hs->liveBits);
         goto fail;
     }
-
+    if (!allocMarkStack(&gcHeap->markContext.stack, hs->absoluteMaxSize)) {
+        LOGE("Can't create markStack");
+        dvmHeapBitmapDelete(&hs->markBits);
+        dvmHeapBitmapDelete(&hs->liveBits);
+        goto fail;
+    }
     gcHeap->markContext.bitmap = &hs->markBits;
     gcHeap->heapSource = hs;
 
@@ -618,16 +655,12 @@
 dvmHeapSourceShutdown(GcHeap **gcHeap)
 {
     if (*gcHeap != NULL && (*gcHeap)->heapSource != NULL) {
-        HeapSource *hs;
-
-        hs = (*gcHeap)->heapSource;
-
+        HeapSource *hs = (*gcHeap)->heapSource;
         assert((char *)*gcHeap >= hs->heapBase);
         assert((char *)*gcHeap < hs->heapBase + hs->heapLength);
-
         dvmHeapBitmapDelete(&hs->liveBits);
         dvmHeapBitmapDelete(&hs->markBits);
-
+        freeMarkStack(&(*gcHeap)->markContext.stack);
         munmap(hs->heapBase, hs->heapLength);
         gHs = NULL;
         *gcHeap = NULL;
diff --git a/vm/alloc/MarkSweep.c b/vm/alloc/MarkSweep.c
index 84c111a..57fdd4d 100644
--- a/vm/alloc/MarkSweep.c
+++ b/vm/alloc/MarkSweep.c
@@ -57,43 +57,57 @@
     return dvmHeapBitmapIsObjectBitSet(ctx->bitmap, obj);
 }
 
+/*
+ * Initializes the stack top and advises the mark stack pages as needed.
+ */
 static bool createMarkStack(GcMarkStack *stack)
 {
-    const Object **limit;
-    const char *name;
-    size_t size;
-
-    /* Create a stack big enough for the worst possible case,
-     * where the heap is perfectly full of the smallest object.
-     * TODO: be better about memory usage; use a smaller stack with
-     *       overflow detection and recovery.
-     */
-    size = dvmHeapSourceGetIdealFootprint() * sizeof(Object*) /
-            (sizeof(Object) + HEAP_SOURCE_CHUNK_OVERHEAD);
-    size = ALIGN_UP_TO_PAGE_SIZE(size);
-    name = "dalvik-mark-stack";
-    limit = dvmAllocRegion(size, PROT_READ | PROT_WRITE, name);
-    if (limit == NULL) {
-        LOGE_GC("Could not mmap %zd-byte ashmem region '%s'", size, name);
-        return false;
-    }
-    stack->limit = limit;
-    stack->base = (const Object **)((uintptr_t)limit + size);
+    assert(stack != NULL);
+    size_t length = dvmHeapSourceGetIdealFootprint() * sizeof(Object*) /
+        (sizeof(Object) + HEAP_SOURCE_CHUNK_OVERHEAD);
+    madvise(stack->base, length, MADV_NORMAL);
     stack->top = stack->base;
     return true;
 }
 
+/*
+ * Assigns NULL to the stack top and advises the mark stack pages as
+ * not needed.
+ */
 static void destroyMarkStack(GcMarkStack *stack)
 {
-    munmap((char *)stack->limit,
-            (uintptr_t)stack->base - (uintptr_t)stack->limit);
-    memset(stack, 0, sizeof(*stack));
+    assert(stack != NULL);
+    madvise(stack->base, stack->length, MADV_DONTNEED);
+    stack->top = NULL;
 }
 
-#define MARK_STACK_PUSH(stack, obj) \
-    do { \
-        *--(stack).top = (obj); \
-    } while (false)
+/*
+ * Pops an object from the mark stack.
+ */
+static void markStackPush(GcMarkStack *stack, const Object *obj)
+{
+    assert(stack != NULL);
+    assert(stack->base <= stack->top);
+    assert(stack->limit > stack->top);
+    assert(obj != NULL);
+    *stack->top = obj;
+    ++stack->top;
+}
+
+/*
+ * Pushes an object on the mark stack.
+ */
+static const Object *markStackPop(GcMarkStack *stack)
+{
+    const Object *obj;
+
+    assert(stack != NULL);
+    assert(stack->base < stack->top);
+    assert(stack->limit > stack->top);
+    --stack->top;
+    obj = *stack->top;
+    return obj;
+}
 
 bool dvmHeapBeginMarkStep(GcMode mode)
 {
@@ -129,7 +143,7 @@
         if (checkFinger && (void *)obj < ctx->finger) {
             /* This object will need to go on the mark stack.
              */
-            MARK_STACK_PUSH(ctx->stack, obj);
+            markStackPush(&ctx->stack, obj);
         }
     }
 }
@@ -502,18 +516,21 @@
     }
 }
 
-static void
-processMarkStack(GcMarkContext *ctx)
+/*
+ * Scan anything that's on the mark stack.  We can't use the bitmaps
+ * anymore, so use a finger that points past the end of them.
+ */
+static void processMarkStack(GcMarkContext *ctx)
 {
-    const Object **const base = ctx->stack.base;
+    GcMarkStack *stack;
 
-    /* Scan anything that's on the mark stack.
-     * We can't use the bitmaps anymore, so use
-     * a finger that points past the end of them.
-     */
+    assert(ctx != NULL);
     ctx->finger = (void *)ULONG_MAX;
-    while (ctx->stack.top != base) {
-        scanObject(*ctx->stack.top++, ctx);
+    stack = &ctx->stack;
+    assert(stack->top >= stack->base);
+    while (stack->top > stack->base) {
+        const Object *obj = markStackPop(stack);
+        scanObject(obj, ctx);
     }
 }
 
diff --git a/vm/alloc/MarkSweep.h b/vm/alloc/MarkSweep.h
index ffdfbd5..59b34e1 100644
--- a/vm/alloc/MarkSweep.h
+++ b/vm/alloc/MarkSweep.h
@@ -19,20 +19,22 @@
 #include "alloc/HeapBitmap.h"
 #include "alloc/HeapSource.h"
 
-/* Downward-growing stack for better cache read behavior.
- */
 typedef struct {
-    /* Lowest address (inclusive)
+    /* Highest address (exclusive)
      */
     const Object **limit;
 
-    /* Current top of the stack (inclusive)
+    /* Current top of the stack (exclusive)
      */
     const Object **top;
 
-    /* Highest address (exclusive)
+    /* Lowest address (inclusive)
      */
     const Object **base;
+
+    /* Maximum stack size, in bytes.
+     */
+    size_t length;
 } GcMarkStack;
 
 /* This is declared publicly so that it can be included in gDvm.gcHeap.