From 4f9be5213afc3e31db170c190f72fd5f91c0e456 Mon Sep 17 00:00:00 2001 From: Ben Cheng Date: Wed, 10 Feb 2010 17:21:39 -0800 Subject: [PATCH] Free memory associated with the trace descriptor of ALL dropped JIT work orders To further reduce the memory consumption only enable the method vs trace compile size stats when WITH_JIT_TUNING is configured. --- vm/compiler/Compiler.c | 10 +++++----- vm/compiler/Frontend.c | 10 ++++++++++ vm/interp/Jit.c | 10 ++++++++++ 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/vm/compiler/Compiler.c b/vm/compiler/Compiler.c index e01ca894a..032b8594e 100644 --- a/vm/compiler/Compiler.c +++ b/vm/compiler/Compiler.c @@ -53,6 +53,9 @@ static CompilerWorkOrder workDequeue(void) * Attempt to enqueue a work order, returning true if successful. * This routine will not block, but simply return if it couldn't * aquire the lock or if the queue is full. + * + * NOTE: Make sure that the caller frees the info pointer if the return value + * is false. */ bool dvmCompilerWorkEnqueue(const u2 *pc, WorkOrderKind kind, void* info) { @@ -62,11 +65,6 @@ bool dvmCompilerWorkEnqueue(const u2 *pc, WorkOrderKind kind, void* info) bool result = true; if (dvmTryLockMutex(&gDvmJit.compilerLock)) { - /* - * Make sure the memory associated with the info pointer is freed for - * dropped work orders. - */ - free(info); return false; // Couldn't acquire the lock } @@ -315,8 +313,10 @@ bool compilerThreadStartup(void) dvmLockMutex(&gDvmJit.compilerLock); +#if defined(WITH_JIT_TUNING) /* Track method-level compilation statistics */ gDvmJit.methodStatsTable = dvmHashTableCreate(32, NULL); +#endif dvmUnlockMutex(&gDvmJit.compilerLock); diff --git a/vm/compiler/Frontend.c b/vm/compiler/Frontend.c index c8e8e5254..0c8a8df0e 100644 --- a/vm/compiler/Frontend.c +++ b/vm/compiler/Frontend.c @@ -191,6 +191,7 @@ static int compareMethod(const CompilerMethodStats *m1, return (int) m1->method - (int) m2->method; } +#if defined(WITH_JIT_TUNING) /* * Analyze each method whose traces are ever compiled. Collect a variety of * statistics like the ratio of exercised vs overall code and code bloat @@ -247,6 +248,7 @@ static CompilerMethodStats *analyzeMethodBody(const Method *method) realMethodEntry->dalvikSize = insnSize * 2; return realMethodEntry; } +#endif /* * Crawl the stack of the thread that requesed compilation to see if any of the @@ -297,7 +299,9 @@ bool dvmCompileTrace(JitTraceDescription *desc, int numMaxInsts, int numBlocks = 0; static int compilationId; CompilationUnit cUnit; +#if defined(WITH_JIT_TUNING) CompilerMethodStats *methodStats; +#endif /* If we've already compiled this trace, just return success */ if (dvmJitGetCodeAddr(startCodePtr) && !info->discardResult) { @@ -307,8 +311,10 @@ bool dvmCompileTrace(JitTraceDescription *desc, int numMaxInsts, compilationId++; memset(&cUnit, 0, sizeof(CompilationUnit)); +#if defined(WITH_JIT_TUNING) /* Locate the entry to store compilation statistics for this method */ methodStats = analyzeMethodBody(desc->method); +#endif /* Initialize the printMe flag */ cUnit.printMe = gDvmJit.printMe; @@ -449,8 +455,10 @@ bool dvmCompileTrace(JitTraceDescription *desc, int numMaxInsts, } } +#if defined(WITH_JIT_TUNING) /* Convert # of half-word to bytes */ methodStats->compiledDalvikSize += traceSize * 2; +#endif /* * Now scan basic blocks containing real code to connect the @@ -745,7 +753,9 @@ bool dvmCompileTrace(JitTraceDescription *desc, int numMaxInsts, /* Success */ if (!cUnit.halveInstCount) { +#if defined(WITH_JIT_TUNING) methodStats->nativeSize += cUnit.totalSize; +#endif return info->codeAddress != NULL; /* Halve the instruction count and retry again */ diff --git a/vm/interp/Jit.c b/vm/interp/Jit.c index 4949b9ce9..ec39c8aa1 100644 --- a/vm/interp/Jit.c +++ b/vm/interp/Jit.c @@ -221,6 +221,10 @@ static void selfVerificationSpinLoop(ShadowSpace *shadowSpace) JitTraceDescription* desc = dvmCopyTraceDescriptor(startPC); if (desc) { dvmCompilerWorkEnqueue(startPC, kWorkOrderTraceDebug, desc); + /* + * This function effectively terminates the VM right here, so not + * freeing the desc pointer when the enqueuing fails is acceptable. + */ } gDvmJit.selfVerificationSpin = true; while(gDvmJit.selfVerificationSpin) sleep(10); @@ -722,6 +726,12 @@ int dvmCheckJit(const u2* pc, Thread* self, InterpState* interpState) if (gDvmJit.blockingMode) { dvmCompilerDrainQueue(); } + } else { + /* + * Make sure the descriptor for the abandoned work order is + * freed. + */ + free(desc); } /* * Reset "trace in progress" flag whether or not we -- 2.11.0