Fix an invoke-interface bug that manifests itself with thread state warnings.
r12 is a scratch register and apparently gcc 4.4 starts to actively use it in
dvmFindInterfaceMethodInCache, the very function that the original live value
is being protected around. This results in useless values setup in the chaining
cell and increases the chances to patch the cell (thus the suspend-all
requests).
Add verbose names for new JIT-related suspend reasons.
With all these changes, the thread state warning will still occur but much less
frequently.
bug 2194174.
diff --git a/vm/compiler/codegen/arm/ArmLIR.h b/vm/compiler/codegen/arm/ArmLIR.h
index 8fedda2..4e97499 100644
--- a/vm/compiler/codegen/arm/ArmLIR.h
+++ b/vm/compiler/codegen/arm/ArmLIR.h
@@ -663,10 +663,10 @@
#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 81dd0e3..799142f 100644
--- a/vm/compiler/codegen/arm/Assemble.c
+++ b/vm/compiler/codegen/arm/Assemble.c
@@ -1246,13 +1246,22 @@
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 @@
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 c0729ab..2713a12 100644
--- a/vm/compiler/codegen/arm/Codegen.c
+++ b/vm/compiler/codegen/arm/Codegen.c
@@ -3218,7 +3218,7 @@
}
/*
* 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 @@
* 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 @@
*/
/* 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 @@
/* 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 @@
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