Jit: Monitor exit, possible fix for Issue 2396073
Two problems with monitor-exit:
1. The Jit code wasn't checking for exception thrown following
unlocks of fat locks using dvmUnlockObject().
2. The mterp interpreter unlock code branched to handle exceptions
thrown during dvmUnlockObject() with the wrong dalvik PC (the
dPC of the unlock, rather than the instruction following the unlock).
Similar issue with the x86 interpreter fixed. Also, deleted armv7-a
MONITOR_ENTER template, which turned out to be identical to the armv5te
one.
diff --git a/vm/compiler/codegen/arm/CodegenDriver.c b/vm/compiler/codegen/arm/CodegenDriver.c
index 99d392d..4048c0a 100644
--- a/vm/compiler/codegen/arm/CodegenDriver.c
+++ b/vm/compiler/codegen/arm/CodegenDriver.c
@@ -1276,6 +1276,15 @@
loadConstant(cUnit, r2, (int)dvmUnlockObject);
/* Do the call */
opReg(cUnit, kOpBlx, r2);
+ opRegImm(cUnit, kOpCmp, r0, 0); /* Did we throw? */
+ ArmLIR *branchOver = opCondBranch(cUnit, kArmCondNe);
+ loadConstant(cUnit, r0,
+ (int) (cUnit->method->insns + mir->offset +
+ dexGetInstrWidthAbs(gDvm.instrWidth, OP_MONITOR_EXIT)));
+ genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
+ ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
+ target->defMask = ENCODE_ALL;
+ branchOver->generic.target = (LIR *) target;
dvmCompilerColbberCallRegs(cUnit);
}
}
diff --git a/vm/compiler/codegen/arm/Thumb2/Gen.c b/vm/compiler/codegen/arm/Thumb2/Gen.c
index 071964a..1390d64 100644
--- a/vm/compiler/codegen/arm/Thumb2/Gen.c
+++ b/vm/compiler/codegen/arm/Thumb2/Gen.c
@@ -253,6 +253,15 @@
sizeof(StackSaveArea) -
offsetof(StackSaveArea, xtra.currentPc));
opReg(cUnit, kOpBlx, r7);
+ opRegImm(cUnit, kOpCmp, r0, 0); /* Did we throw? */
+ ArmLIR *branchOver = opCondBranch(cUnit, kArmCondNe);
+ loadConstant(cUnit, r0,
+ (int) (cUnit->method->insns + mir->offset +
+ dexGetInstrWidthAbs(gDvm.instrWidth, OP_MONITOR_EXIT)));
+ genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
+ ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
+ target->defMask = ENCODE_ALL;
+ branchOver->generic.target = (LIR *) target;
dvmCompilerColbberCallRegs(cUnit);
}
diff --git a/vm/compiler/template/armv7-a/TEMPLATE_MONITOR_ENTER.S b/vm/compiler/template/armv7-a/TEMPLATE_MONITOR_ENTER.S
deleted file mode 100644
index 114bbdc..0000000
--- a/vm/compiler/template/armv7-a/TEMPLATE_MONITOR_ENTER.S
+++ /dev/null
@@ -1,32 +0,0 @@
- /*
- * 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]
-#if defined(EXIT_STATS)
- mov r0, #kHeavyweightMonitor
-#endif
- bx r2
-
diff --git a/vm/compiler/template/config-armv7-a b/vm/compiler/template/config-armv7-a
index 29d9019..be7af31 100644
--- a/vm/compiler/template/config-armv7-a
+++ b/vm/compiler/template/config-armv7-a
@@ -46,7 +46,7 @@
op TEMPLATE_STRING_COMPARETO armv5te
op TEMPLATE_STRING_INDEXOF armv5te
op TEMPLATE_INTERPRET armv5te
- op TEMPLATE_MONITOR_ENTER armv7-a
+ op TEMPLATE_MONITOR_ENTER armv5te
op TEMPLATE_MONITOR_ENTER_DEBUG armv5te
op-end
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
index 6d9b7f0..e83e773 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
@@ -1371,23 +1371,17 @@
.balign 4
.global dvmCompiler_TEMPLATE_MONITOR_ENTER
dvmCompiler_TEMPLATE_MONITOR_ENTER:
-/* File: armv7-a/TEMPLATE_MONITOR_ENTER.S */
+/* File: armv5te/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.
+ * 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