summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--vm/Thread.c7
-rw-r--r--vm/Thread.h3
-rw-r--r--vm/compiler/codegen/arm/ArmLIR.h4
-rw-r--r--vm/compiler/codegen/arm/Assemble.c21
-rw-r--r--vm/compiler/codegen/arm/Codegen.c26
-rw-r--r--vm/interp/Jit.c4
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;
}