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.