diff options
| -rw-r--r-- | vm/Thread.c | 7 | ||||
| -rw-r--r-- | vm/Thread.h | 3 | ||||
| -rw-r--r-- | vm/compiler/codegen/arm/ArmLIR.h | 4 | ||||
| -rw-r--r-- | vm/compiler/codegen/arm/Assemble.c | 21 | ||||
| -rw-r--r-- | vm/compiler/codegen/arm/Codegen.c | 26 | ||||
| -rw-r--r-- | vm/interp/Jit.c | 4 |
6 files changed, 43 insertions, 22 deletions
diff --git a/vm/Thread.c b/vm/Thread.c index 7ca3dc71c..55e27f65b 100644 --- a/vm/Thread.c +++ b/vm/Thread.c @@ -521,6 +521,10 @@ static const char* getSuspendCauseStr(SuspendCause why) case SUSPEND_FOR_DEBUG: return "debug"; case SUSPEND_FOR_DEBUG_EVENT: return "debug-event"; case SUSPEND_FOR_STACK_DUMP: return "stack-dump"; +#if defined(WITH_JIT) + case SUSPEND_FOR_TBL_RESIZE: return "table-resize"; + case SUSPEND_FOR_IC_PATCH: return "inline-cache-patch"; +#endif default: return "UNKNOWN"; } } @@ -559,6 +563,9 @@ static void lockThreadSuspend(const char* who, SuspendCause why) * * Could be the debugger telling us to resume at roughly * the same time we're posting an event. + * + * Could be two app threads both want to patch predicted + * chaining cells around the same time. */ LOGI("threadid=%d ODD: want thread-suspend lock (%s:%s)," " it's held, no suspend pending\n", diff --git a/vm/Thread.h b/vm/Thread.h index 179a920c2..d834f7b0b 100644 --- a/vm/Thread.h +++ b/vm/Thread.h @@ -275,7 +275,8 @@ typedef enum SuspendCause { SUSPEND_FOR_STACK_DUMP, SUSPEND_FOR_DEX_OPT, #if defined(WITH_JIT) - SUSPEND_FOR_JIT, + SUSPEND_FOR_TBL_RESIZE, + SUSPEND_FOR_IC_PATCH, #endif } SuspendCause; void dvmSuspendThread(Thread* thread); diff --git a/vm/compiler/codegen/arm/ArmLIR.h b/vm/compiler/codegen/arm/ArmLIR.h index 8fedda24c..4e9749994 100644 --- a/vm/compiler/codegen/arm/ArmLIR.h +++ b/vm/compiler/codegen/arm/ArmLIR.h @@ -663,10 +663,10 @@ typedef struct PredictedChainingCell { #define PREDICTED_CHAIN_COUNTER_INIT 0 /* Used when the callee is not compiled yet */ -#define PREDICTED_CHAIN_COUNTER_DELAY 16 +#define PREDICTED_CHAIN_COUNTER_DELAY 512 /* Rechain after this many mis-predictions have happened */ -#define PREDICTED_CHAIN_COUNTER_RECHAIN 1024 +#define PREDICTED_CHAIN_COUNTER_RECHAIN 8192 /* Used if the resolved callee is a native method */ #define PREDICTED_CHAIN_COUNTER_AVOID 0x7fffffff diff --git a/vm/compiler/codegen/arm/Assemble.c b/vm/compiler/codegen/arm/Assemble.c index 81dd0e39a..799142f41 100644 --- a/vm/compiler/codegen/arm/Assemble.c +++ b/vm/compiler/codegen/arm/Assemble.c @@ -1246,13 +1246,22 @@ const Method *dvmJitToPatchPredictedChain(const Method *method, cell->counter = PREDICTED_CHAIN_COUNTER_DELAY; cacheflush((long) cell, (long) (cell+1), 0); COMPILER_TRACE_CHAINING( - LOGD("Jit Runtime: predicted chain %p to method %s delayed", - cell, method->name)); + LOGD("Jit Runtime: predicted chain %p to method %s%s delayed", + cell, method->clazz->descriptor, method->name)); goto done; } + /* + * Bump up the counter first just in case other mutator threads are in + * nearby territory to also attempt to rechain this cell. This is not + * done in a thread-safe way and doesn't need to be since the consequence + * of the race condition [rare] is two back-to-back suspend-all attempts, + * which will be handled correctly. + */ + cell->counter = PREDICTED_CHAIN_COUNTER_AVOID; + /* Stop the world */ - dvmSuspendAllThreads(SUSPEND_FOR_JIT); + dvmSuspendAllThreads(SUSPEND_FOR_IC_PATCH); int baseAddr = (int) cell + 4; // PC is cur_addr + 4 int branchOffset = tgtAddr - baseAddr; @@ -1266,12 +1275,16 @@ const Method *dvmJitToPatchPredictedChain(const Method *method, cell->branch = assembleBXPair(branchOffset); cell->clazz = clazz; cell->method = method; + /* + * Reset the counter again in case other mutator threads got invoked + * between the previous rest and dvmSuspendAllThreads call. + */ cell->counter = PREDICTED_CHAIN_COUNTER_RECHAIN; cacheflush((long) cell, (long) (cell+1), 0); /* All done - resume all other threads */ - dvmResumeAllThreads(SUSPEND_FOR_JIT); + dvmResumeAllThreads(SUSPEND_FOR_IC_PATCH); #endif done: diff --git a/vm/compiler/codegen/arm/Codegen.c b/vm/compiler/codegen/arm/Codegen.c index c0729abf7..2713a1213 100644 --- a/vm/compiler/codegen/arm/Codegen.c +++ b/vm/compiler/codegen/arm/Codegen.c @@ -3218,7 +3218,7 @@ static bool handleFmt35c_3rc(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb, } /* * TODO: When we move to using upper registers in Thumb2, make sure - * the register allocater is told that r9, r10, & r12 are killed + * the register allocater is told that r8, r9, & r10 are killed * here. */ /* @@ -3240,21 +3240,21 @@ static bool handleFmt35c_3rc(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb, * 0x426a9ad2 : blx_2 see above --+ PREDICTED_CHAIN * 0x426a9ad4 : b 0x426a9b0c --> off to the predicted chain * 0x426a9ad6 : b 0x426a9afe --> punt to the interpreter - * 0x426a9ad8 : mov r9, r1 --+ - * 0x426a9ada : mov r10, r2 | - * 0x426a9adc : mov r12, r3 | + * 0x426a9ad8 : mov r8, r1 --+ + * 0x426a9ada : mov r9, r2 | + * 0x426a9adc : mov r10, r3 | * 0x426a9ade : mov r0, r3 | * 0x426a9ae0 : mov r1, #74 | dvmFindInterfaceMethodInCache * 0x426a9ae2 : ldr r2, [pc, #76] | * 0x426a9ae4 : ldr r3, [pc, #68] | * 0x426a9ae6 : ldr r7, [pc, #64] | * 0x426a9ae8 : blx r7 --+ - * 0x426a9aea : mov r1, r9 --> r1 <- rechain count + * 0x426a9aea : mov r1, r8 --> r1 <- rechain count * 0x426a9aec : cmp r1, #0 --> compare against 0 * 0x426a9aee : bgt 0x426a9af8 --> >=0? don't rechain * 0x426a9af0 : ldr r7, [r6, #96] --+ - * 0x426a9af2 : mov r2, r10 | dvmJitToPatchPredictedChain - * 0x426a9af4 : mov r3, r12 | + * 0x426a9af2 : mov r2, r9 | dvmJitToPatchPredictedChain + * 0x426a9af4 : mov r3, r10 | * 0x426a9af6 : blx r7 --+ * 0x426a9af8 : add r1, pc, #8 --> r1 <- &retChainingCell * 0x426a9afa : blx_1 0x426a9098 --+ TEMPLATE_INVOKE_METHOD_NO_OPT @@ -3343,9 +3343,9 @@ static bool handleFmt35c_3rc(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb, */ /* Save count, &predictedChainCell, and class to high regs first */ - opRegReg(cUnit, OP_MOV, r9, r1); - opRegReg(cUnit, OP_MOV, r10, r2); - opRegReg(cUnit, OP_MOV, r12, r3); + opRegReg(cUnit, OP_MOV, r8, r1); + opRegReg(cUnit, OP_MOV, r9, r2); + opRegReg(cUnit, OP_MOV, r10, r3); /* r0 now contains this->clazz */ opRegReg(cUnit, OP_MOV, r0, r3); @@ -3365,7 +3365,7 @@ static bool handleFmt35c_3rc(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb, /* r0 = calleeMethod (returned from dvmFindInterfaceMethodInCache */ - opRegReg(cUnit, OP_MOV, r1, r9); + opRegReg(cUnit, OP_MOV, r1, r8); /* Check if rechain limit is reached */ opRegImm(cUnit, OP_CMP, r1, 0, rNone); @@ -3375,8 +3375,8 @@ static bool handleFmt35c_3rc(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb, loadWordDisp(cUnit, rGLUE, offsetof(InterpState, jitToInterpEntries.dvmJitToPatchPredictedChain), r7); - opRegReg(cUnit, OP_MOV, r2, r10); - opRegReg(cUnit, OP_MOV, r3, r12); + opRegReg(cUnit, OP_MOV, r2, r9); + opRegReg(cUnit, OP_MOV, r3, r10); /* * r0 = calleeMethod diff --git a/vm/interp/Jit.c b/vm/interp/Jit.c index 1d8665785..c149035fc 100644 --- a/vm/interp/Jit.c +++ b/vm/interp/Jit.c @@ -963,7 +963,7 @@ bool dvmJitResizeJitTable( unsigned int size ) } /* Stop all other interpreting/jit'ng threads */ - dvmSuspendAllThreads(SUSPEND_FOR_JIT); + dvmSuspendAllThreads(SUSPEND_FOR_TBL_RESIZE); pOldTable = gDvmJit.pJitEntryTable; oldSize = gDvmJit.jitTableSize; @@ -1000,7 +1000,7 @@ bool dvmJitResizeJitTable( unsigned int size ) free(pOldTable); /* Restart the world */ - dvmResumeAllThreads(SUSPEND_FOR_JIT); + dvmResumeAllThreads(SUSPEND_FOR_TBL_RESIZE); return false; } |
