diff options
author | Ben Cheng <bccheng@android.com> | 2011-02-18 17:12:42 -0800 |
---|---|---|
committer | Ben Cheng <bccheng@android.com> | 2011-03-02 13:45:54 -0800 |
commit | 20d7e6c67af128d5bf7cc003564a8122c4101c84 (patch) | |
tree | 2c15767179646dd5c24c87c1a8ebfaedd42686c4 /vm/compiler/codegen/arm/armv7-a-neon/MethodCodegenDriver.c | |
parent | 131ec9ff58fcc6a7440297e2cbee23df93d2974d (diff) | |
download | android_dalvik-20d7e6c67af128d5bf7cc003564a8122c4101c84.tar.gz android_dalvik-20d7e6c67af128d5bf7cc003564a8122c4101c84.tar.bz2 android_dalvik-20d7e6c67af128d5bf7cc003564a8122c4101c84.zip |
Handle OP_THROW in the method JIT.
The current implementation is to reconstruct the leaf Dalvik frame and
punt to the interpreter, since the amount of work involed to match
each catch block and walk through the stack frames is just not worth
JIT'ing.
Additional changes:
- Fixed a control-flow bug where a block that ends with a throw shouldn't
have a fall-through block.
- Fixed a code cache lookup bug so that method-based compilation is
guaranteed a slot in the profiling table.
- Created separate handler routines based on opcode format for the
method-based JIT.
- Renamed a few core registers that also have special meanings to the
VM or ARM architecture.
Change-Id: I429b3633f281a0e04d352ae17a1c4f4a41bab156
Diffstat (limited to 'vm/compiler/codegen/arm/armv7-a-neon/MethodCodegenDriver.c')
-rw-r--r-- | vm/compiler/codegen/arm/armv7-a-neon/MethodCodegenDriver.c | 279 |
1 files changed, 252 insertions, 27 deletions
diff --git a/vm/compiler/codegen/arm/armv7-a-neon/MethodCodegenDriver.c b/vm/compiler/codegen/arm/armv7-a-neon/MethodCodegenDriver.c index c25ab8346..5a08b60ac 100644 --- a/vm/compiler/codegen/arm/armv7-a-neon/MethodCodegenDriver.c +++ b/vm/compiler/codegen/arm/armv7-a-neon/MethodCodegenDriver.c @@ -14,6 +14,228 @@ * limitations under the License. */ +/* + * Rebuild the interpreter frame then punt to the interpreter to execute + * instruction at specified PC. + * + * Currently parameters are passed to the current frame, so we just need to + * grow the stack save area above it, fill certain fields in StackSaveArea and + * Thread that are skipped during whole-method invocation (specified below), + * then return to the interpreter. + * + * StackSaveArea: + * - prevSave + * - prevFrame + * - savedPc + * - returnAddr + * - method + * + * Thread: + * - method + * - methodClassDex + * - curFrame + */ +static void genMethodInflateAndPunt(CompilationUnit *cUnit, MIR *mir, + BasicBlock *bb) +{ + int oldStackSave = r0; + int newStackSave = r1; + int oldFP = r2; + int savedPC = r3; + int currentPC = r4PC; + int returnAddr = r7; + int method = r8; + int pDvmDex = r9; + + /* + * TODO: check whether to raise the stack overflow exception when growing + * the stack save area. + */ + + /* Send everything to home location */ + dvmCompilerFlushAllRegs(cUnit); + + /* oldStackSave = r5FP + sizeof(current frame) */ + opRegRegImm(cUnit, kOpAdd, oldStackSave, r5FP, + cUnit->method->registersSize * 4); + /* oldFP = oldStackSave + sizeof(stackSaveArea) */ + opRegRegImm(cUnit, kOpAdd, oldFP, oldStackSave, sizeof(StackSaveArea)); + /* newStackSave = r5FP - sizeof(StackSaveArea) */ + opRegRegImm(cUnit, kOpSub, newStackSave, r5FP, sizeof(StackSaveArea)); + + loadWordDisp(cUnit, r13sp, 0, savedPC); + loadConstant(cUnit, currentPC, (int) (cUnit->method->insns + mir->offset)); + loadConstant(cUnit, method, (int) cUnit->method); + loadConstant(cUnit, pDvmDex, (int) cUnit->method->clazz->pDvmDex); +#ifdef EASY_GDB + /* newStackSave->prevSave = oldStackSave */ + storeWordDisp(cUnit, newStackSave, offsetof(StackSaveArea, prevSave), + oldStackSave); +#endif + /* newStackSave->prevSave = oldStackSave */ + storeWordDisp(cUnit, newStackSave, offsetof(StackSaveArea, prevFrame), + oldFP); + /* newStackSave->savedPc = savedPC */ + storeWordDisp(cUnit, newStackSave, offsetof(StackSaveArea, savedPc), + savedPC); + /* return address */ + loadConstant(cUnit, returnAddr, 0); + storeWordDisp(cUnit, newStackSave, offsetof(StackSaveArea, returnAddr), + returnAddr); + /* newStackSave->method = method */ + storeWordDisp(cUnit, newStackSave, offsetof(StackSaveArea, method), method); + /* thread->method = method */ + storeWordDisp(cUnit, r6SELF, offsetof(InterpSaveState, method), method); + /* thread->curFrame = current FP */ + storeWordDisp(cUnit, r6SELF, offsetof(Thread, curFrame), r5FP); + /* thread->methodClassDex = pDvmDex */ + storeWordDisp(cUnit, r6SELF, offsetof(InterpSaveState, methodClassDex), + pDvmDex); + /* Restore the stack pointer */ + opRegImm(cUnit, kOpAdd, r13sp, 16); + genPuntToInterp(cUnit, mir->offset); +} + +/* + * The following are the first-level codegen routines that analyze the format + * of each bytecode then either dispatch special purpose codegen routines + * or produce corresponding Thumb instructions directly. + * + * TODO - most them are just pass-through to the trace-based versions for now + */ +static bool handleMethodFmt10t_Fmt20t_Fmt30t(CompilationUnit *cUnit, MIR *mir, + BasicBlock *bb, ArmLIR *labelList) +{ + /* backward branch? */ + bool backwardBranch = (bb->taken->startOffset <= mir->offset); + + if (backwardBranch && gDvmJit.genSuspendPoll) { + genSuspendPoll(cUnit, mir); + } + + /* For OP_GOTO, OP_GOTO_16, and OP_GOTO_32 */ + genUnconditionalBranch(cUnit, &labelList[bb->taken->id]); + return false; +} + +static bool handleMethodFmt10x(CompilationUnit *cUnit, MIR *mir) +{ + Opcode dalvikOpcode = mir->dalvikInsn.opcode; + switch (dalvikOpcode) { + case OP_RETURN_VOID: + return false; + default: + return handleFmt10x(cUnit, mir); + } +} + +static bool handleMethodFmt11n_Fmt31i(CompilationUnit *cUnit, MIR *mir) +{ + return handleFmt11n_Fmt31i(cUnit, mir); +} + +static bool handleMethodFmt11x(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb, + ArmLIR *labelList) +{ + Opcode dalvikOpcode = mir->dalvikInsn.opcode; + switch (dalvikOpcode) { + case OP_THROW: + genMethodInflateAndPunt(cUnit, mir, bb); + return false; + default: + return handleFmt11x(cUnit, mir); + } +} + +static bool handleMethodFmt12x(CompilationUnit *cUnit, MIR *mir) +{ + return handleFmt12x(cUnit, mir); +} + +static bool handleMethodFmt20bc_Fmt40sc(CompilationUnit *cUnit, MIR *mir) +{ + return handleFmt20bc_Fmt40sc(cUnit, mir); +} + +static bool handleMethodFmt21c_Fmt31c_Fmt41c(CompilationUnit *cUnit, MIR *mir) +{ + return handleFmt21c_Fmt31c_Fmt41c(cUnit, mir); +} + +static bool handleMethodFmt21h(CompilationUnit *cUnit, MIR *mir) +{ + return handleFmt21h(cUnit, mir); +} + +static bool handleMethodFmt21s(CompilationUnit *cUnit, MIR *mir) +{ + return handleFmt21s(cUnit, mir); +} + +static bool handleMethodFmt21t(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb, + ArmLIR *labelList) +{ + return handleFmt21t(cUnit, mir, bb, labelList); +} + +static bool handleMethodFmt22b_Fmt22s(CompilationUnit *cUnit, MIR *mir) +{ + return handleFmt22b_Fmt22s(cUnit, mir); +} + +static bool handleMethodFmt22c_Fmt52c(CompilationUnit *cUnit, MIR *mir) +{ + return handleFmt22c_Fmt52c(cUnit, mir); +} + +static bool handleMethodFmt22cs(CompilationUnit *cUnit, MIR *mir) +{ + return handleFmt22cs(cUnit, mir); +} + +static bool handleMethodFmt22t(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb, + ArmLIR *labelList) +{ + return handleFmt22t(cUnit, mir, bb, labelList); +} + +static bool handleMethodFmt22x_Fmt32x(CompilationUnit *cUnit, MIR *mir) +{ + return handleFmt22x_Fmt32x(cUnit, mir); +} + +static bool handleMethodFmt23x(CompilationUnit *cUnit, MIR *mir) +{ + return handleFmt23x(cUnit, mir); +} + +static bool handleMethodFmt31t(CompilationUnit *cUnit, MIR *mir) +{ + return handleFmt31t(cUnit, mir); +} + +static bool handleMethodFmt35c_3rc_5rc(CompilationUnit *cUnit, MIR *mir, + BasicBlock *bb, ArmLIR *labelList) +{ + return handleFmt35c_3rc_5rc(cUnit, mir, bb, labelList); +} + +static bool handleMethodFmt35ms_3rms(CompilationUnit *cUnit, MIR *mir, + BasicBlock *bb, ArmLIR *labelList) +{ + return handleFmt35ms_3rms(cUnit, mir, bb, labelList); +} + +static bool handleMethodExecuteInline(CompilationUnit *cUnit, MIR *mir) +{ + return handleExecuteInline(cUnit, mir); +} + +static bool handleMethodFmt51l(CompilationUnit *cUnit, MIR *mir) +{ + return handleFmt51l(cUnit, mir); +} + /* Handle the content in each basic block */ static bool methodBlockCodeGen(CompilationUnit *cUnit, BasicBlock *bb) { @@ -34,12 +256,15 @@ static bool methodBlockCodeGen(CompilationUnit *cUnit, BasicBlock *bb) ArmLIR *headLIR = NULL; if (bb->blockType == kMethodEntryBlock) { - opImm(cUnit, kOpPush, (1 << rlr | 1 << rFP)); - opRegImm(cUnit, kOpSub, rFP, + /* r0 = callsitePC */ + opImm(cUnit, kOpPush, (1 << r0 | 1 << r1 | 1 << r5FP | 1 << r14lr)); + opRegImm(cUnit, kOpSub, r5FP, sizeof(StackSaveArea) + cUnit->method->registersSize * 4); } else if (bb->blockType == kMethodExitBlock) { - opImm(cUnit, kOpPop, (1 << rpc | 1 << rFP)); + /* No need to pop r0 and r1 */ + opRegImm(cUnit, kOpAdd, r13sp, 8); + opImm(cUnit, kOpPop, (1 << r5FP | 1 << r15pc)); } for (mir = bb->firstMIRInsn; mir; mir = mir->next) { @@ -88,81 +313,81 @@ static bool methodBlockCodeGen(CompilationUnit *cUnit, BasicBlock *bb) case kFmt10t: case kFmt20t: case kFmt30t: - notHandled = handleFmt10t_Fmt20t_Fmt30t(cUnit, - mir, bb, labelList); + notHandled = handleMethodFmt10t_Fmt20t_Fmt30t(cUnit, mir, bb, + labelList); break; case kFmt10x: - notHandled = handleFmt10x(cUnit, mir); + notHandled = handleMethodFmt10x(cUnit, mir); break; case kFmt11n: case kFmt31i: - notHandled = handleFmt11n_Fmt31i(cUnit, mir); + notHandled = handleMethodFmt11n_Fmt31i(cUnit, mir); break; case kFmt11x: - notHandled = handleFmt11x(cUnit, mir); + notHandled = handleMethodFmt11x(cUnit, mir, bb, labelList); break; case kFmt12x: - notHandled = handleFmt12x(cUnit, mir); + notHandled = handleMethodFmt12x(cUnit, mir); break; case kFmt20bc: case kFmt40sc: - notHandled = handleFmt20bc_Fmt40sc(cUnit, mir); + notHandled = handleMethodFmt20bc_Fmt40sc(cUnit, mir); break; case kFmt21c: case kFmt31c: case kFmt41c: - notHandled = handleFmt21c_Fmt31c_Fmt41c(cUnit, mir); + notHandled = handleMethodFmt21c_Fmt31c_Fmt41c(cUnit, mir); break; case kFmt21h: - notHandled = handleFmt21h(cUnit, mir); + notHandled = handleMethodFmt21h(cUnit, mir); break; case kFmt21s: - notHandled = handleFmt21s(cUnit, mir); + notHandled = handleMethodFmt21s(cUnit, mir); break; case kFmt21t: - notHandled = handleFmt21t(cUnit, mir, bb, labelList); + notHandled = handleMethodFmt21t(cUnit, mir, bb, labelList); break; case kFmt22b: case kFmt22s: - notHandled = handleFmt22b_Fmt22s(cUnit, mir); + notHandled = handleMethodFmt22b_Fmt22s(cUnit, mir); break; case kFmt22c: case kFmt52c: - notHandled = handleFmt22c_Fmt52c(cUnit, mir); + notHandled = handleMethodFmt22c_Fmt52c(cUnit, mir); break; case kFmt22cs: - notHandled = handleFmt22cs(cUnit, mir); + notHandled = handleMethodFmt22cs(cUnit, mir); break; case kFmt22t: - notHandled = handleFmt22t(cUnit, mir, bb, labelList); + notHandled = handleMethodFmt22t(cUnit, mir, bb, labelList); break; case kFmt22x: case kFmt32x: - notHandled = handleFmt22x_Fmt32x(cUnit, mir); + notHandled = handleMethodFmt22x_Fmt32x(cUnit, mir); break; case kFmt23x: - notHandled = handleFmt23x(cUnit, mir); + notHandled = handleMethodFmt23x(cUnit, mir); break; case kFmt31t: - notHandled = handleFmt31t(cUnit, mir); + notHandled = handleMethodFmt31t(cUnit, mir); break; case kFmt3rc: case kFmt35c: case kFmt5rc: - notHandled = handleFmt35c_3rc_5rc(cUnit, mir, bb, - labelList); + notHandled = handleMethodFmt35c_3rc_5rc(cUnit, mir, bb, + labelList); break; case kFmt3rms: case kFmt35ms: - notHandled = handleFmt35ms_3rms(cUnit, mir, bb, - labelList); + notHandled = handleMethodFmt35ms_3rms(cUnit, mir, bb, + labelList); break; case kFmt35mi: case kFmt3rmi: - notHandled = handleExecuteInline(cUnit, mir); + notHandled = handleMethodExecuteInline(cUnit, mir); break; case kFmt51l: - notHandled = handleFmt51l(cUnit, mir); + notHandled = handleMethodFmt51l(cUnit, mir); break; default: notHandled = true; |