summaryrefslogtreecommitdiffstats
path: root/vm/compiler
diff options
context:
space:
mode:
authorBill Buzbee <buzbee@google.com>2010-02-02 11:04:33 -0800
committerBill Buzbee <buzbee@google.com>2010-02-03 14:47:49 -0800
commitf5ceaebfe5633a16b11a7073d2bf36b5bb0c9945 (patch)
tree5502cdcbf8742846adeb33c060e57e9baa12ec44 /vm/compiler
parent5043da6f678448f6111d1a0dcc584f5adf01b526 (diff)
downloadandroid_dalvik-f5ceaebfe5633a16b11a7073d2bf36b5bb0c9945.tar.gz
android_dalvik-f5ceaebfe5633a16b11a7073d2bf36b5bb0c9945.tar.bz2
android_dalvik-f5ceaebfe5633a16b11a7073d2bf36b5bb0c9945.zip
Jit: Rework monitor enter/exit to simplify thread suspension
The Jit must stop all threads in order to flush the translation cache (and other tables). Threads which are blocked in a monitor wait cause some headache here because they effectively hold a references to the translation cache (though the return address on the native stack). The new model introduced in this CL is that for the fast path of monitor enter, control is allowed to resume in the translation cache. However, if we need to do a heavyweight lock (which may cause us to block) control does not return to the translation cache but instead bails out to the interpreter. This allows us to safely clear the code cache even if some threads are in THREAD_MONITOR state.
Diffstat (limited to 'vm/compiler')
-rw-r--r--vm/compiler/codegen/arm/CodegenDriver.c53
-rw-r--r--vm/compiler/codegen/arm/Thumb2/Gen.c32
-rw-r--r--vm/compiler/template/armv5te-vfp/TemplateOpList.h2
-rw-r--r--vm/compiler/template/armv5te/TEMPLATE_MONITOR_ENTER.S23
-rw-r--r--vm/compiler/template/armv5te/TEMPLATE_MONITOR_ENTER_DEBUG.S29
-rw-r--r--vm/compiler/template/armv5te/TemplateOpList.h2
-rw-r--r--vm/compiler/template/armv5te/footer.S2
-rw-r--r--vm/compiler/template/armv7-a/TEMPLATE_MONITOR_ENTER.S29
-rw-r--r--vm/compiler/template/armv7-a/TemplateOpList.h2
-rw-r--r--vm/compiler/template/config-armv5te-vfp2
-rw-r--r--vm/compiler/template/config-armv7-a3
-rw-r--r--vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S66
-rw-r--r--vm/compiler/template/out/CompilerTemplateAsm-armv5te.S66
-rw-r--r--vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S72
14 files changed, 339 insertions, 44 deletions
diff --git a/vm/compiler/codegen/arm/CodegenDriver.c b/vm/compiler/codegen/arm/CodegenDriver.c
index 648d8f4d6..5be07aa3d 100644
--- a/vm/compiler/codegen/arm/CodegenDriver.c
+++ b/vm/compiler/codegen/arm/CodegenDriver.c
@@ -1693,46 +1693,41 @@ static void genInterpSingleStep(CompilationUnit *cUnit, MIR *mir)
opReg(cUnit, kOpBlx, r2);
}
+/*
+ * To prevent a thread in a monitor wait from blocking the Jit from
+ * resetting the code cache, heavyweight monitor lock will not
+ * be allowed to return to an existing translation. Instead, we will
+ * handle them by branching to a handler, which will in turn call the
+ * runtime lock routine and then branch directly back to the
+ * interpreter main loop. Given the high cost of the heavyweight
+ * lock operation, this additional cost should be slight (especially when
+ * considering that we expect the vast majority of lock operations to
+ * use the fast-path thin lock bypass).
+ */
static void genMonitorPortable(CompilationUnit *cUnit, MIR *mir)
{
bool isEnter = (mir->dalvikInsn.opCode == OP_MONITOR_ENTER);
- flushAllRegs(cUnit); /* Send everything to home location */
genExportPC(cUnit, mir);
+ flushAllRegs(cUnit); /* Send everything to home location */
RegLocation rlSrc = getSrcLoc(cUnit, mir, 0);
loadValueDirectFixed(cUnit, rlSrc, r1);
loadWordDisp(cUnit, rGLUE, offsetof(InterpState, self), r0);
+ genNullCheck(cUnit, rlSrc.sRegLow, r1, mir->offset, NULL);
if (isEnter) {
- loadConstant(cUnit, r2, (int)dvmLockObject);
+ /* Get dPC of next insn */
+ loadConstant(cUnit, r4PC, (int)(cUnit->method->insns + mir->offset +
+ dexGetInstrWidthAbs(gDvm.instrWidth, OP_MONITOR_ENTER)));
+#if defined(WITH_DEADLOCK_PREDICTION)
+ genDispatchToHandler(cUnit, TEMPLATE_MONITOR_ENTER_DEBUG);
+#else
+ genDispatchToHandler(cUnit, TEMPLATE_MONITOR_ENTER);
+#endif
} else {
loadConstant(cUnit, r2, (int)dvmUnlockObject);
+ /* Do the call */
+ opReg(cUnit, kOpBlx, r2);
+ clobberCallRegs(cUnit);
}
- genNullCheck(cUnit, rlSrc.sRegLow, r1, mir->offset, NULL);
- /* Do the call */
- opReg(cUnit, kOpBlx, r2);
- /*
- * Refresh Jit's on/off status, which may have changed if we were
- * sent to VM_MONITOR state above.
- * TUNING: pointer chase, but must reload following call
- */
- loadWordDisp(cUnit, rGLUE, offsetof(InterpState, ppJitProfTable), r0);
- loadWordDisp(cUnit, r0, 0, r0);
- storeWordDisp(cUnit, rGLUE, offsetof(InterpState, pJitProfTable), r0);
-#if defined(WITH_DEADLOCK_PREDICTION)
- if (isEnter) {
- loadWordDisp(cUnit, rGLUE, offsetof(InterpState, self), r0);
- loadWordDisp(cUnit, r0, offsetof(Thread, exception), r1);
- opRegImm(cUnit, kOpCmp, r1, 0);
- ArmLIR *branchOver = opCondBranch(cUnit, kArmCondEq);
- loadConstant(cUnit, r0,
- (int) (cUnit->method->insns + mir->offset));
- genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
- /* noreturn */
- ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
- target->defMask = ENCODE_ALL;
- branchOver->generic.target = (LIR *) target;
- }
-#endif
- clobberCallRegs(cUnit);
}
/*
diff --git a/vm/compiler/codegen/arm/Thumb2/Gen.c b/vm/compiler/codegen/arm/Thumb2/Gen.c
index 5f2a6a259..1f947c2ad 100644
--- a/vm/compiler/codegen/arm/Thumb2/Gen.c
+++ b/vm/compiler/codegen/arm/Thumb2/Gen.c
@@ -231,26 +231,30 @@ static void genMonitor(CompilationUnit *cUnit, MIR *mir)
offsetof(Object, lock) >> 2);
}
// Note: end of IT block
-
branch = newLIR2(cUnit, kThumb2Cbz, r2, 0);
+ // Export PC (part 1)
+ loadConstant(cUnit, r3, (int) (cUnit->method->insns + mir->offset));
+
if (enter) {
- loadConstant(cUnit, r7, (int)dvmLockObject);
+ /* Get dPC of next insn */
+ loadConstant(cUnit, r4PC, (int)(cUnit->method->insns + mir->offset +
+ dexGetInstrWidthAbs(gDvm.instrWidth, OP_MONITOR_ENTER)));
+ // Export PC (part 2)
+ newLIR3(cUnit, kThumb2StrRRI8Predec, r3, rFP,
+ sizeof(StackSaveArea) -
+ offsetof(StackSaveArea, xtra.currentPc));
+ /* Call template, and don't return */
+ genDispatchToHandler(cUnit, TEMPLATE_MONITOR_ENTER);
} else {
loadConstant(cUnit, r7, (int)dvmUnlockObject);
+ // Export PC (part 2)
+ newLIR3(cUnit, kThumb2StrRRI8Predec, r3, rFP,
+ sizeof(StackSaveArea) -
+ offsetof(StackSaveArea, xtra.currentPc));
+ opReg(cUnit, kOpBlx, r7);
+ clobberCallRegs(cUnit);
}
- genExportPC(cUnit, mir);
- opReg(cUnit, kOpBlx, r7);
- /*
- * Refresh Jit's on/off status, which may have changed if we were
- * sent to VM_MONITOR state above.
- * TUNING: pointer chase, but must refresh following return from call
- */
- loadWordDisp(cUnit, rGLUE, offsetof(InterpState, ppJitProfTable), r0);
- loadWordDisp(cUnit, r0, 0, r0);
- storeWordDisp(cUnit, rGLUE, offsetof(InterpState, pJitProfTable), r0);
-
- clobberCallRegs(cUnit);
// Resume here
target = newLIR0(cUnit, kArmPseudoTargetLabel);
diff --git a/vm/compiler/template/armv5te-vfp/TemplateOpList.h b/vm/compiler/template/armv5te-vfp/TemplateOpList.h
index d414e1be4..8855d46ee 100644
--- a/vm/compiler/template/armv5te-vfp/TemplateOpList.h
+++ b/vm/compiler/template/armv5te-vfp/TemplateOpList.h
@@ -56,3 +56,5 @@ JIT_TEMPLATE(RESTORE_STATE)
JIT_TEMPLATE(STRING_COMPARETO)
JIT_TEMPLATE(STRING_INDEXOF)
JIT_TEMPLATE(INTERPRET)
+JIT_TEMPLATE(MONITOR_ENTER)
+JIT_TEMPLATE(MONITOR_ENTER_DEBUG)
diff --git a/vm/compiler/template/armv5te/TEMPLATE_MONITOR_ENTER.S b/vm/compiler/template/armv5te/TEMPLATE_MONITOR_ENTER.S
new file mode 100644
index 000000000..fa931bbeb
--- /dev/null
+++ b/vm/compiler/template/armv5te/TEMPLATE_MONITOR_ENTER.S
@@ -0,0 +1,23 @@
+ /*
+ * Call out to the runtime to lock an object. Because this thread
+ * may have been suspended in THREAD_MONITOR state and the Jit's
+ * translation cache subsequently cleared, we cannot return directly.
+ * Instead, unconditionally transition to the interpreter to resume.
+ *
+ * On entry:
+ * r0 - self pointer
+ * r1 - the object (which has already been null-checked by the caller
+ * r4 - the Dalvik PC of the following instruction.
+ *
+ ldr r2, .LdvmLockObject
+ mov r3, #0 @ Record that we're not returning
+ str r3, [r0, #offThread_inJitCodeCache]
+ blx r2 @ dvmLockObject(self, obj)
+ @ refresh Jit's on/off status
+ ldr r0, [rGLUE, #offGlue_ppJitProfTable]
+ ldr r0, [r0]
+ ldr r2, .LdvmJitToInterpNoChain
+ str r0, [rGLUE, #offGlue_pJitProfTable]
+ @ Bail to interpreter - no chain [note - r4 still contains rPC]
+ bx r2
+
diff --git a/vm/compiler/template/armv5te/TEMPLATE_MONITOR_ENTER_DEBUG.S b/vm/compiler/template/armv5te/TEMPLATE_MONITOR_ENTER_DEBUG.S
new file mode 100644
index 000000000..c030cec64
--- /dev/null
+++ b/vm/compiler/template/armv5te/TEMPLATE_MONITOR_ENTER_DEBUG.S
@@ -0,0 +1,29 @@
+ /*
+ * To support deadlock prediction, this version of MONITOR_ENTER
+ * will always call the heavyweight dvmLockObject, check for an
+ * exception and then bail out to the interpreter.
+ *
+ * On entry:
+ * r0 - self pointer
+ * r1 - the object (which has already been null-checked by the caller
+ * r4 - the Dalvik PC of the following instruction.
+ *
+ */
+ ldr r2, .LdvmLockObject
+ mov r3, #0 @ Record that we're not returning
+ str r3, [r0, #offThread_inJitCodeCache]
+ blx r2 @ dvmLockObject(self, obj)
+ @ refresh Jit's on/off status & test for exception
+ ldr r0, [rGLUE, #offGlue_ppJitProfTable]
+ ldr r1, [rGLUE, #offGlue_self]
+ ldr r0, [r0]
+ ldr r1, [r1, #offThread_exception]
+ str r0, [rGLUE, #offGlue_pJitProfTable]
+ cmp r1, #0
+ beq 1f
+ ldr r2, .LhandleException
+ sub r0, r4, #2 @ roll dPC back to this monitor instruction
+ bx r2
+1:
+ @ Bail to interpreter - no chain [note - r4 still contains rPC]
+ ldr pc, .LdvmJitToInterpNoChain
diff --git a/vm/compiler/template/armv5te/TemplateOpList.h b/vm/compiler/template/armv5te/TemplateOpList.h
index 1b5e6ea99..c7ae80a28 100644
--- a/vm/compiler/template/armv5te/TemplateOpList.h
+++ b/vm/compiler/template/armv5te/TemplateOpList.h
@@ -41,3 +41,5 @@ JIT_TEMPLATE(RESTORE_STATE)
JIT_TEMPLATE(STRING_COMPARETO)
JIT_TEMPLATE(STRING_INDEXOF)
JIT_TEMPLATE(INTERPRET)
+JIT_TEMPLATE(MONITOR_ENTER)
+JIT_TEMPLATE(MONITOR_ENTER_DEBUG)
diff --git a/vm/compiler/template/armv5te/footer.S b/vm/compiler/template/armv5te/footer.S
index 5d76f4869..0e817a638 100644
--- a/vm/compiler/template/armv5te/footer.S
+++ b/vm/compiler/template/armv5te/footer.S
@@ -77,6 +77,8 @@
.word dvmMterpStdBail
.LdvmMterpCommonExceptionThrown:
.word dvmMterpCommonExceptionThrown
+.LdvmLockObject:
+ .word dvmLockObject
.L__aeabi_cdcmple:
.word __aeabi_cdcmple
.L__aeabi_cfcmple:
diff --git a/vm/compiler/template/armv7-a/TEMPLATE_MONITOR_ENTER.S b/vm/compiler/template/armv7-a/TEMPLATE_MONITOR_ENTER.S
new file mode 100644
index 000000000..a26e52816
--- /dev/null
+++ b/vm/compiler/template/armv7-a/TEMPLATE_MONITOR_ENTER.S
@@ -0,0 +1,29 @@
+ /*
+ * thumb2 specific.
+ *
+ * In this variant of the MONITOR_ENTER handler, we assume that
+ * the test for the simple thin lock case has already been done.
+ * So, we'll just call dvmLockObject(), refresh the
+ * jit's on/off switch on return and then bail out to the interpreter.
+ * We have to bail to the interpreter because the translation cache
+ * may have been cleared while we were blocked on a monitor in
+ * dvmLockObject.
+ *
+ * On entry:
+ * r0 - self pointer
+ * r1 - the object (which has already been null-checked by the caller
+ * r4 - the Dalvik PC of the following instruction.
+ *
+ */
+ ldr r2, .LdvmLockObject
+ mov r3, #0 @ Record that we're not returning
+ str r3, [r0, #offThread_inJitCodeCache]
+ blx r2 @ dvmLockObject(self, obj)
+ @ refresh Jit's on/off status
+ ldr r0, [rGLUE, #offGlue_ppJitProfTable]
+ ldr r0, [r0]
+ ldr r2, .LdvmJitToInterpNoChain
+ str r0, [rGLUE, #offGlue_pJitProfTable]
+ @ Bail to interpreter - no chain [note - r4 still contains rPC]
+ bx r2
+
diff --git a/vm/compiler/template/armv7-a/TemplateOpList.h b/vm/compiler/template/armv7-a/TemplateOpList.h
index d414e1be4..8855d46ee 100644
--- a/vm/compiler/template/armv7-a/TemplateOpList.h
+++ b/vm/compiler/template/armv7-a/TemplateOpList.h
@@ -56,3 +56,5 @@ JIT_TEMPLATE(RESTORE_STATE)
JIT_TEMPLATE(STRING_COMPARETO)
JIT_TEMPLATE(STRING_INDEXOF)
JIT_TEMPLATE(INTERPRET)
+JIT_TEMPLATE(MONITOR_ENTER)
+JIT_TEMPLATE(MONITOR_ENTER_DEBUG)
diff --git a/vm/compiler/template/config-armv5te-vfp b/vm/compiler/template/config-armv5te-vfp
index 0a1c7c7de..1b02261eb 100644
--- a/vm/compiler/template/config-armv5te-vfp
+++ b/vm/compiler/template/config-armv5te-vfp
@@ -46,6 +46,8 @@ op-start armv5te-vfp
op TEMPLATE_STRING_COMPARETO armv5te
op TEMPLATE_STRING_INDEXOF armv5te
op TEMPLATE_INTERPRET armv5te
+ op TEMPLATE_MONITOR_ENTER armv5te
+ op TEMPLATE_MONITOR_ENTER_DEBUG armv5te
op-end
diff --git a/vm/compiler/template/config-armv7-a b/vm/compiler/template/config-armv7-a
index 89fbb2315..29d90197f 100644
--- a/vm/compiler/template/config-armv7-a
+++ b/vm/compiler/template/config-armv7-a
@@ -46,7 +46,8 @@ op-start armv5te-vfp
op TEMPLATE_STRING_COMPARETO armv5te
op TEMPLATE_STRING_INDEXOF armv5te
op TEMPLATE_INTERPRET armv5te
-
+ op TEMPLATE_MONITOR_ENTER armv7-a
+ op TEMPLATE_MONITOR_ENTER_DEBUG armv5te
op-end
# "helper" code for C; include if you use any of the C stubs (this generates
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S b/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
index afd69f353..3090a1776 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
@@ -1388,6 +1388,70 @@ dvmCompiler_TEMPLATE_INTERPRET:
.LinterpPunt:
.word dvmJitToInterpPunt
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_MONITOR_ENTER
+dvmCompiler_TEMPLATE_MONITOR_ENTER:
+/* File: armv5te/TEMPLATE_MONITOR_ENTER.S */
+ /*
+ * Call out to the runtime to lock an object. Because this thread
+ * may have been suspended in THREAD_MONITOR state and the Jit's
+ * translation cache subsequently cleared, we cannot return directly.
+ * Instead, unconditionally transition to the interpreter to resume.
+ *
+ * On entry:
+ * r0 - self pointer
+ * r1 - the object (which has already been null-checked by the caller
+ * r4 - the Dalvik PC of the following instruction.
+ *
+ ldr r2, .LdvmLockObject
+ mov r3, #0 @ Record that we're not returning
+ str r3, [r0, #offThread_inJitCodeCache]
+ blx r2 @ dvmLockObject(self, obj)
+ @ refresh Jit's on/off status
+ ldr r0, [rGLUE, #offGlue_ppJitProfTable]
+ ldr r0, [r0]
+ ldr r2, .LdvmJitToInterpNoChain
+ str r0, [rGLUE, #offGlue_pJitProfTable]
+ @ Bail to interpreter - no chain [note - r4 still contains rPC]
+ bx r2
+
+
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG
+dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG:
+/* File: armv5te/TEMPLATE_MONITOR_ENTER_DEBUG.S */
+ /*
+ * To support deadlock prediction, this version of MONITOR_ENTER
+ * will always call the heavyweight dvmLockObject, check for an
+ * exception and then bail out to the interpreter.
+ *
+ * On entry:
+ * r0 - self pointer
+ * r1 - the object (which has already been null-checked by the caller
+ * r4 - the Dalvik PC of the following instruction.
+ *
+ */
+ ldr r2, .LdvmLockObject
+ mov r3, #0 @ Record that we're not returning
+ str r3, [r0, #offThread_inJitCodeCache]
+ blx r2 @ dvmLockObject(self, obj)
+ @ refresh Jit's on/off status & test for exception
+ ldr r0, [rGLUE, #offGlue_ppJitProfTable]
+ ldr r1, [rGLUE, #offGlue_self]
+ ldr r0, [r0]
+ ldr r1, [r1, #offThread_exception]
+ str r0, [rGLUE, #offGlue_pJitProfTable]
+ cmp r1, #0
+ beq 1f
+ ldr r2, .LhandleException
+ sub r0, r4, #2 @ roll dPC back to this monitor instruction
+ bx r2
+1:
+ @ Bail to interpreter - no chain [note - r4 still contains rPC]
+ ldr pc, .LdvmJitToInterpNoChain
+
.size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
/* File: armv5te/footer.S */
/*
@@ -1469,6 +1533,8 @@ dvmCompiler_TEMPLATE_INTERPRET:
.word dvmMterpStdBail
.LdvmMterpCommonExceptionThrown:
.word dvmMterpCommonExceptionThrown
+.LdvmLockObject:
+ .word dvmLockObject
.L__aeabi_cdcmple:
.word __aeabi_cdcmple
.L__aeabi_cfcmple:
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S b/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
index d73e0101c..ffb978634 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
@@ -1113,6 +1113,70 @@ dvmCompiler_TEMPLATE_INTERPRET:
.LinterpPunt:
.word dvmJitToInterpPunt
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_MONITOR_ENTER
+dvmCompiler_TEMPLATE_MONITOR_ENTER:
+/* File: armv5te/TEMPLATE_MONITOR_ENTER.S */
+ /*
+ * Call out to the runtime to lock an object. Because this thread
+ * may have been suspended in THREAD_MONITOR state and the Jit's
+ * translation cache subsequently cleared, we cannot return directly.
+ * Instead, unconditionally transition to the interpreter to resume.
+ *
+ * On entry:
+ * r0 - self pointer
+ * r1 - the object (which has already been null-checked by the caller
+ * r4 - the Dalvik PC of the following instruction.
+ *
+ ldr r2, .LdvmLockObject
+ mov r3, #0 @ Record that we're not returning
+ str r3, [r0, #offThread_inJitCodeCache]
+ blx r2 @ dvmLockObject(self, obj)
+ @ refresh Jit's on/off status
+ ldr r0, [rGLUE, #offGlue_ppJitProfTable]
+ ldr r0, [r0]
+ ldr r2, .LdvmJitToInterpNoChain
+ str r0, [rGLUE, #offGlue_pJitProfTable]
+ @ Bail to interpreter - no chain [note - r4 still contains rPC]
+ bx r2
+
+
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG
+dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG:
+/* File: armv5te/TEMPLATE_MONITOR_ENTER_DEBUG.S */
+ /*
+ * To support deadlock prediction, this version of MONITOR_ENTER
+ * will always call the heavyweight dvmLockObject, check for an
+ * exception and then bail out to the interpreter.
+ *
+ * On entry:
+ * r0 - self pointer
+ * r1 - the object (which has already been null-checked by the caller
+ * r4 - the Dalvik PC of the following instruction.
+ *
+ */
+ ldr r2, .LdvmLockObject
+ mov r3, #0 @ Record that we're not returning
+ str r3, [r0, #offThread_inJitCodeCache]
+ blx r2 @ dvmLockObject(self, obj)
+ @ refresh Jit's on/off status & test for exception
+ ldr r0, [rGLUE, #offGlue_ppJitProfTable]
+ ldr r1, [rGLUE, #offGlue_self]
+ ldr r0, [r0]
+ ldr r1, [r1, #offThread_exception]
+ str r0, [rGLUE, #offGlue_pJitProfTable]
+ cmp r1, #0
+ beq 1f
+ ldr r2, .LhandleException
+ sub r0, r4, #2 @ roll dPC back to this monitor instruction
+ bx r2
+1:
+ @ Bail to interpreter - no chain [note - r4 still contains rPC]
+ ldr pc, .LdvmJitToInterpNoChain
+
.size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
/* File: armv5te/footer.S */
/*
@@ -1194,6 +1258,8 @@ dvmCompiler_TEMPLATE_INTERPRET:
.word dvmMterpStdBail
.LdvmMterpCommonExceptionThrown:
.word dvmMterpCommonExceptionThrown
+.LdvmLockObject:
+ .word dvmLockObject
.L__aeabi_cdcmple:
.word __aeabi_cdcmple
.L__aeabi_cfcmple:
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
index 12af0d27c..b157ff3f0 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
@@ -1388,6 +1388,76 @@ dvmCompiler_TEMPLATE_INTERPRET:
.LinterpPunt:
.word dvmJitToInterpPunt
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_MONITOR_ENTER
+dvmCompiler_TEMPLATE_MONITOR_ENTER:
+/* File: armv7-a/TEMPLATE_MONITOR_ENTER.S */
+ /*
+ * thumb2 specific.
+ *
+ * In this variant of the MONITOR_ENTER handler, we assume that
+ * the test for the simple thin lock case has already been done.
+ * So, we'll just call dvmLockObject(), refresh the
+ * jit's on/off switch on return and then bail out to the interpreter.
+ * We have to bail to the interpreter because the translation cache
+ * may have been cleared while we were blocked on a monitor in
+ * dvmLockObject.
+ *
+ * On entry:
+ * r0 - self pointer
+ * r1 - the object (which has already been null-checked by the caller
+ * r4 - the Dalvik PC of the following instruction.
+ *
+ */
+ ldr r2, .LdvmLockObject
+ mov r3, #0 @ Record that we're not returning
+ str r3, [r0, #offThread_inJitCodeCache]
+ blx r2 @ dvmLockObject(self, obj)
+ @ refresh Jit's on/off status
+ ldr r0, [rGLUE, #offGlue_ppJitProfTable]
+ ldr r0, [r0]
+ ldr r2, .LdvmJitToInterpNoChain
+ str r0, [rGLUE, #offGlue_pJitProfTable]
+ @ Bail to interpreter - no chain [note - r4 still contains rPC]
+ bx r2
+
+
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG
+dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG:
+/* File: armv5te/TEMPLATE_MONITOR_ENTER_DEBUG.S */
+ /*
+ * To support deadlock prediction, this version of MONITOR_ENTER
+ * will always call the heavyweight dvmLockObject, check for an
+ * exception and then bail out to the interpreter.
+ *
+ * On entry:
+ * r0 - self pointer
+ * r1 - the object (which has already been null-checked by the caller
+ * r4 - the Dalvik PC of the following instruction.
+ *
+ */
+ ldr r2, .LdvmLockObject
+ mov r3, #0 @ Record that we're not returning
+ str r3, [r0, #offThread_inJitCodeCache]
+ blx r2 @ dvmLockObject(self, obj)
+ @ refresh Jit's on/off status & test for exception
+ ldr r0, [rGLUE, #offGlue_ppJitProfTable]
+ ldr r1, [rGLUE, #offGlue_self]
+ ldr r0, [r0]
+ ldr r1, [r1, #offThread_exception]
+ str r0, [rGLUE, #offGlue_pJitProfTable]
+ cmp r1, #0
+ beq 1f
+ ldr r2, .LhandleException
+ sub r0, r4, #2 @ roll dPC back to this monitor instruction
+ bx r2
+1:
+ @ Bail to interpreter - no chain [note - r4 still contains rPC]
+ ldr pc, .LdvmJitToInterpNoChain
+
.size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
/* File: armv5te/footer.S */
/*
@@ -1469,6 +1539,8 @@ dvmCompiler_TEMPLATE_INTERPRET:
.word dvmMterpStdBail
.LdvmMterpCommonExceptionThrown:
.word dvmMterpCommonExceptionThrown
+.LdvmLockObject:
+ .word dvmLockObject
.L__aeabi_cdcmple:
.word __aeabi_cdcmple
.L__aeabi_cfcmple: