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);
}
}
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);
}
+++ /dev/null
- /*
- * 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
-
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
.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
EXPORT_PC() @ before fetch: export the PC
GET_VREG(r1, r2) @ r1<- vAA (object)
cmp r1, #0 @ null object?
- beq common_errNullObject @ yes
+ beq 1f @ yes
ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
bl dvmUnlockObject @ r0<- success for unlock(self, obj)
cmp r0, #0 @ failed?
- beq common_exceptionThrown @ yes, exception is pending
FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST
+ beq common_exceptionThrown @ yes, exception is pending
GET_INST_OPCODE(ip) @ extract opcode from rINST
GOTO_OPCODE(ip) @ jump to next instruction
+1:
+ FETCH_ADVANCE_INST(1) @ advance before throw
+ b common_errNullObject
EXPORT_PC() @ before fetch: export the PC
GET_VREG(r1, r2) @ r1<- vAA (object)
cmp r1, #0 @ null object?
- beq common_errNullObject @ yes
+ beq 1f @ yes
ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
bl dvmUnlockObject @ r0<- success for unlock(self, obj)
cmp r0, #0 @ failed?
- beq common_exceptionThrown @ yes, exception is pending
FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST
+ beq common_exceptionThrown @ yes, exception is pending
GET_INST_OPCODE(ip) @ extract opcode from rINST
GOTO_OPCODE(ip) @ jump to next instruction
+1:
+ FETCH_ADVANCE_INST(1) @ advance before throw
+ b common_errNullObject
/* ------------------------------ */
EXPORT_PC() @ before fetch: export the PC
GET_VREG(r1, r2) @ r1<- vAA (object)
cmp r1, #0 @ null object?
- beq common_errNullObject @ yes
+ beq 1f @ yes
ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
bl dvmUnlockObject @ r0<- success for unlock(self, obj)
cmp r0, #0 @ failed?
- beq common_exceptionThrown @ yes, exception is pending
FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST
+ beq common_exceptionThrown @ yes, exception is pending
GET_INST_OPCODE(ip) @ extract opcode from rINST
GOTO_OPCODE(ip) @ jump to next instruction
+1:
+ FETCH_ADVANCE_INST(1) @ advance before throw
+ b common_errNullObject
/* ------------------------------ */
EXPORT_PC() @ before fetch: export the PC
GET_VREG(r1, r2) @ r1<- vAA (object)
cmp r1, #0 @ null object?
- beq common_errNullObject @ yes
+ beq 1f @ yes
ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
bl dvmUnlockObject @ r0<- success for unlock(self, obj)
cmp r0, #0 @ failed?
- beq common_exceptionThrown @ yes, exception is pending
FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST
+ beq common_exceptionThrown @ yes, exception is pending
GET_INST_OPCODE(ip) @ extract opcode from rINST
GOTO_OPCODE(ip) @ jump to next instruction
+1:
+ FETCH_ADVANCE_INST(1) @ advance before throw
+ b common_errNullObject
/* ------------------------------ */
EXPORT_PC() @ before fetch: export the PC
GET_VREG(r1, r2) @ r1<- vAA (object)
cmp r1, #0 @ null object?
- beq common_errNullObject @ yes
+ beq 1f @ yes
ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
bl dvmUnlockObject @ r0<- success for unlock(self, obj)
cmp r0, #0 @ failed?
- beq common_exceptionThrown @ yes, exception is pending
FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST
+ beq common_exceptionThrown @ yes, exception is pending
GET_INST_OPCODE(ip) @ extract opcode from rINST
GOTO_OPCODE(ip) @ jump to next instruction
+1:
+ FETCH_ADVANCE_INST(1) @ advance before throw
+ b common_errNullObject
/* ------------------------------ */
GET_GLUE(%ecx)
EXPORT_PC()
testl %eax,%eax # null object?
- je common_errNullObject # go if so
+ je .LOP_MONITOR_EXIT_errNullObject # go if so
movl offGlue_self(%ecx),%ecx # ecx<- glue->self
movl %eax,OUT_ARG1(%esp)
SPILL(rPC)
UNSPILL(rPC)
FETCH_INST_WORD(1)
testl %eax,%eax # success?
- je common_exceptionThrown # no, exception pending
ADVANCE_PC(1)
+ je common_exceptionThrown # no, exception pending
GOTO_NEXT
+.LOP_MONITOR_EXIT_errNullObject:
+ ADVANCE_PC(1) # advance before throw
+ jmp common_errNullObject
/* continuation for OP_CHECK_CAST */
GET_GLUE(%ecx)
EXPORT_PC()
testl %eax,%eax # null object?
- je common_errNullObject # go if so
+ je .L${opcode}_errNullObject # go if so
movl offGlue_self(%ecx),%ecx # ecx<- glue->self
movl %eax,OUT_ARG1(%esp)
SPILL(rPC)
UNSPILL(rPC)
FETCH_INST_WORD(1)
testl %eax,%eax # success?
- je common_exceptionThrown # no, exception pending
ADVANCE_PC(1)
+ je common_exceptionThrown # no, exception pending
GOTO_NEXT
+.L${opcode}_errNullObject:
+ ADVANCE_PC(1) # advance before throw
+ jmp common_errNullObject