From cfdeca37fcaa27c37bad5077223e4d1e87f1182e Mon Sep 17 00:00:00 2001 From: Ben Cheng Date: Fri, 14 Jan 2011 11:36:46 -0800 Subject: Add runtime support for method based compilation. Enhanced code cache management to accommodate both trace and method compilations. Also implemented a hacky dispatch routine for virtual leaf methods. Microbenchmark showed 3x speedup in leaf method invocation. Change-Id: I79d95b7300ba993667b3aa221c1df9c7b0583521 --- .../codegen/arm/armv7-a-neon/MethodCodegenDriver.c | 227 +++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 vm/compiler/codegen/arm/armv7-a-neon/MethodCodegenDriver.c (limited to 'vm/compiler/codegen/arm/armv7-a-neon/MethodCodegenDriver.c') diff --git a/vm/compiler/codegen/arm/armv7-a-neon/MethodCodegenDriver.c b/vm/compiler/codegen/arm/armv7-a-neon/MethodCodegenDriver.c new file mode 100644 index 000000000..c25ab8346 --- /dev/null +++ b/vm/compiler/codegen/arm/armv7-a-neon/MethodCodegenDriver.c @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Handle the content in each basic block */ +static bool methodBlockCodeGen(CompilationUnit *cUnit, BasicBlock *bb) +{ + MIR *mir; + ArmLIR *labelList = (ArmLIR *) cUnit->blockLabelList; + int blockId = bb->id; + + cUnit->curBlock = bb; + labelList[blockId].operands[0] = bb->startOffset; + + /* Insert the block label */ + labelList[blockId].opcode = kArmPseudoNormalBlockLabel; + dvmCompilerAppendLIR(cUnit, (LIR *) &labelList[blockId]); + + dvmCompilerClobberAllRegs(cUnit); + dvmCompilerResetNullCheck(cUnit); + + ArmLIR *headLIR = NULL; + + if (bb->blockType == kMethodEntryBlock) { + opImm(cUnit, kOpPush, (1 << rlr | 1 << rFP)); + opRegImm(cUnit, kOpSub, rFP, + sizeof(StackSaveArea) + cUnit->method->registersSize * 4); + + } else if (bb->blockType == kMethodExitBlock) { + opImm(cUnit, kOpPop, (1 << rpc | 1 << rFP)); + } + + for (mir = bb->firstMIRInsn; mir; mir = mir->next) { + + dvmCompilerResetRegPool(cUnit); + if (gDvmJit.disableOpt & (1 << kTrackLiveTemps)) { + dvmCompilerClobberAllRegs(cUnit); + } + + if (gDvmJit.disableOpt & (1 << kSuppressLoads)) { + dvmCompilerResetDefTracking(cUnit); + } + + Opcode dalvikOpcode = mir->dalvikInsn.opcode; + InstructionFormat dalvikFormat = + dexGetFormatFromOpcode(dalvikOpcode); + + ArmLIR *boundaryLIR; + + /* + * Don't generate the boundary LIR unless we are debugging this + * trace or we need a scheduling barrier. + */ + if (headLIR == NULL || cUnit->printMe == true) { + boundaryLIR = + newLIR2(cUnit, kArmPseudoDalvikByteCodeBoundary, + mir->offset, + (int) dvmCompilerGetDalvikDisassembly( + &mir->dalvikInsn, "")); + /* Remember the first LIR for this block */ + if (headLIR == NULL) { + headLIR = boundaryLIR; + /* Set the first boundaryLIR as a scheduling barrier */ + headLIR->defMask = ENCODE_ALL; + } + } + + /* Don't generate the SSA annotation unless verbose mode is on */ + if (cUnit->printMe && mir->ssaRep) { + char *ssaString = dvmCompilerGetSSAString(cUnit, mir->ssaRep); + newLIR1(cUnit, kArmPseudoSSARep, (int) ssaString); + } + + bool notHandled; + switch (dalvikFormat) { + case kFmt10t: + case kFmt20t: + case kFmt30t: + notHandled = handleFmt10t_Fmt20t_Fmt30t(cUnit, + mir, bb, labelList); + break; + case kFmt10x: + notHandled = handleFmt10x(cUnit, mir); + break; + case kFmt11n: + case kFmt31i: + notHandled = handleFmt11n_Fmt31i(cUnit, mir); + break; + case kFmt11x: + notHandled = handleFmt11x(cUnit, mir); + break; + case kFmt12x: + notHandled = handleFmt12x(cUnit, mir); + break; + case kFmt20bc: + case kFmt40sc: + notHandled = handleFmt20bc_Fmt40sc(cUnit, mir); + break; + case kFmt21c: + case kFmt31c: + case kFmt41c: + notHandled = handleFmt21c_Fmt31c_Fmt41c(cUnit, mir); + break; + case kFmt21h: + notHandled = handleFmt21h(cUnit, mir); + break; + case kFmt21s: + notHandled = handleFmt21s(cUnit, mir); + break; + case kFmt21t: + notHandled = handleFmt21t(cUnit, mir, bb, labelList); + break; + case kFmt22b: + case kFmt22s: + notHandled = handleFmt22b_Fmt22s(cUnit, mir); + break; + case kFmt22c: + case kFmt52c: + notHandled = handleFmt22c_Fmt52c(cUnit, mir); + break; + case kFmt22cs: + notHandled = handleFmt22cs(cUnit, mir); + break; + case kFmt22t: + notHandled = handleFmt22t(cUnit, mir, bb, labelList); + break; + case kFmt22x: + case kFmt32x: + notHandled = handleFmt22x_Fmt32x(cUnit, mir); + break; + case kFmt23x: + notHandled = handleFmt23x(cUnit, mir); + break; + case kFmt31t: + notHandled = handleFmt31t(cUnit, mir); + break; + case kFmt3rc: + case kFmt35c: + case kFmt5rc: + notHandled = handleFmt35c_3rc_5rc(cUnit, mir, bb, + labelList); + break; + case kFmt3rms: + case kFmt35ms: + notHandled = handleFmt35ms_3rms(cUnit, mir, bb, + labelList); + break; + case kFmt35mi: + case kFmt3rmi: + notHandled = handleExecuteInline(cUnit, mir); + break; + case kFmt51l: + notHandled = handleFmt51l(cUnit, mir); + break; + default: + notHandled = true; + break; + } + + /* FIXME - to be implemented */ + if (notHandled == true && dalvikOpcode >= kNumPackedOpcodes) { + notHandled = false; + } + + if (notHandled) { + LOGE("%#06x: Opcode 0x%x (%s) / Fmt %d not handled\n", + mir->offset, + dalvikOpcode, dexGetOpcodeName(dalvikOpcode), + dalvikFormat); + dvmCompilerAbort(cUnit); + break; + } + } + + if (headLIR) { + /* + * Eliminate redundant loads/stores and delay stores into later + * slots + */ + dvmCompilerApplyLocalOptimizations(cUnit, (LIR *) headLIR, + cUnit->lastLIRInsn); + + /* + * Generate an unconditional branch to the fallthrough block. + */ + if (bb->fallThrough) { + genUnconditionalBranch(cUnit, + &labelList[bb->fallThrough->id]); + } + } + return false; +} + +void dvmCompilerMethodMIR2LIR(CompilationUnit *cUnit) +{ + // FIXME - enable method compilation for selected routines here + if (strcmp(cUnit->method->name, "add")) return; + + /* Used to hold the labels of each block */ + cUnit->blockLabelList = + (void *) dvmCompilerNew(sizeof(ArmLIR) * cUnit->numBlocks, true); + + dvmCompilerDataFlowAnalysisDispatcher(cUnit, methodBlockCodeGen, + kPreOrderDFSTraversal, + false /* isIterative */); + + dvmCompilerApplyGlobalOptimizations(cUnit); + + // FIXME - temporarily enable verbose printing for all methods + cUnit->printMe = true; + +#if defined(WITH_SELF_VERIFICATION) + selfVerificationBranchInsertPass(cUnit); +#endif +} -- cgit v1.2.3