diff options
| -rw-r--r-- | src/compiler.cc | 2 | ||||
| -rw-r--r-- | src/compiler/Frontend.cc | 109 | ||||
| -rw-r--r-- | src/compiler/Ralloc.cc | 54 | ||||
| -rw-r--r-- | src/compiler/codegen/Ralloc.h | 1 | ||||
| -rw-r--r-- | src/compiler/codegen/RallocUtil.cc | 40 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/ArchFactory.cc | 3 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/ArmRallocUtil.cc | 32 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/MethodCodegenDriver.cc | 43 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/Thumb2/Gen.cc | 2 | ||||
| -rw-r--r-- | src/compiler_test.cc | 7 | ||||
| -rw-r--r-- | test/IntMath/IntMath.java | 42 |
11 files changed, 198 insertions, 137 deletions
diff --git a/src/compiler.cc b/src/compiler.cc index e2d72f54c6..4e3c0529e5 100644 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -128,7 +128,7 @@ void Compiler::CompileMethod(Method* method) { } else if (method->IsAbstract()) { // TODO: This might be also noted in the ClassLinker. // Probably makes more sense to do here? - UNIMPLEMENTED(FATAL) << "compile stub to throw AbstractMethodError"; + UNIMPLEMENTED(WARNING) << "compile stub to throw AbstractMethodError"; } else { oatCompileMethod(method, kThumb2); } diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc index 64d701eb7d..8488606c42 100644 --- a/src/compiler/Frontend.cc +++ b/src/compiler/Frontend.cc @@ -394,63 +394,44 @@ static bool verifyPredInfo(CompilationUnit* cUnit, BasicBlock* bb) /* Identify code range in try blocks and set up the empty catch blocks */ static void processTryCatchBlocks(CompilationUnit* cUnit) { - - UNIMPLEMENTED(WARNING) << "Need to finish processTryCatchBlocks()"; -#if 0 - const Method* meth = cUnit->method; - const DexCode *pCode = dvmGetMethodCode(meth); - int triesSize = pCode->triesSize; - int i; + const Method* method = cUnit->method; + art::ClassLinker* class_linker = art::Runtime::Current()->GetClassLinker(); + const art::DexFile& dex_file = class_linker->FindDexFile( + method->GetDeclaringClass()->GetDexCache()); + const art::DexFile::CodeItem* code_item = + dex_file.GetCodeItem(method->GetCodeItemOffset()); + int triesSize = code_item->tries_size_; int offset; if (triesSize == 0) { return; } - const DexTry* pTries = dexGetTries(pCode); ArenaBitVector* tryBlockAddr = cUnit->tryBlockAddr; - /* Mark all the insn offsets in Try blocks */ - for (i = 0; i < triesSize; i++) { - const DexTry* pTry = &pTries[i]; - /* all in 16-bit units */ - int startOffset = pTry->startAddr; - int endOffset = startOffset + pTry->insnCount; - + for (int i = 0; i < triesSize; i++) { + const art::DexFile::TryItem* pTry = + art::DexFile::dexGetTryItems(*code_item, i); + int startOffset = pTry->start_addr_; + int endOffset = startOffset + pTry->insn_count_; for (offset = startOffset; offset < endOffset; offset++) { oatSetBit(tryBlockAddr, offset); } } - /* Iterate over each of the handlers to enqueue the empty Catch blocks */ - offset = dexGetFirstHandlerOffset(pCode); - int handlersSize = dexGetHandlersSize(pCode); + // Iterate over each of the handlers to enqueue the empty Catch blocks + const art::byte* handlers_ptr = + art::DexFile::dexGetCatchHandlerData(*code_item, 0); + uint32_t handlers_size = art::DecodeUnsignedLeb128(&handlers_ptr); + for (uint32_t idx = 0; idx < handlers_size; idx++) { + art::DexFile::CatchHandlerIterator iterator(handlers_ptr); - for (i = 0; i < handlersSize; i++) { - DexCatchIterator iterator; - dexCatchIteratorInit(&iterator, pCode, offset); - - for (;;) { - DexCatchHandler* handler = dexCatchIteratorNext(&iterator); - - if (handler == NULL) { - break; - } - - /* - * Create dummy catch blocks first. Since these are created before - * other blocks are processed, "split" is specified as false. - */ - findBlock(cUnit, handler->address, - /* split */ - false, - /* create */ - true); + for (; !iterator.HasNext(); iterator.Next()) { + uint32_t address = iterator.Get().address_; + findBlock(cUnit, address, false /* split */, true /*create*/); } - - offset = dexCatchIteratorGetEndOffset(&iterator, pCode); + handlers_ptr = iterator.GetData(); } -#endif } /* Process instructions with the kInstrCanBranch flag */ @@ -613,45 +594,36 @@ static void processCanThrow(CompilationUnit* cUnit, BasicBlock* curBlock, ArenaBitVector* tryBlockAddr, const u2* codePtr, const u2* codeEnd) { - UNIMPLEMENTED(WARNING) << "Need to complete processCanThrow"; -#if 0 + const Method* method = cUnit->method; - const DexCode* dexCode = dvmGetMethodCode(method); + art::ClassLinker* class_linker = art::Runtime::Current()->GetClassLinker(); + const art::DexFile& dex_file = class_linker->FindDexFile( + method->GetDeclaringClass()->GetDexCache()); + const art::DexFile::CodeItem* code_item = + dex_file.GetCodeItem(method->GetCodeItemOffset()); /* In try block */ if (oatIsBitSet(tryBlockAddr, curOffset)) { - DexCatchIterator iterator; - - if (!dexFindCatchHandler(&iterator, dexCode, curOffset)) { - LOG(FATAL) << "Catch block not found in dexfile for insn " << - curOffset << " in " << method->name; + art::DexFile::CatchHandlerIterator iterator = + art::DexFile::dexFindCatchHandler(*code_item, curOffset); - } if (curBlock->successorBlockList.blockListType != kNotUsed) { LOG(FATAL) << "Successor block list already in use: " << (int)curBlock->successorBlockList.blockListType; } + curBlock->successorBlockList.blockListType = kCatch; oatInitGrowableList(&curBlock->successorBlockList.blocks, 2); - for (;;) { - DexCatchHandler* handler = dexCatchIteratorNext(&iterator); - - if (handler == NULL) { - break; - } - - BasicBlock *catchBlock = findBlock(cUnit, handler->address, - /* split */ - false, - /* create */ - false); - + for (;!iterator.HasNext(); iterator.Next()) { + BasicBlock *catchBlock = findBlock(cUnit, iterator.Get().address_, + false /* split*/, + false /* creat */); SuccessorBlockInfo *successorBlockInfo = - (SuccessorBlockInfo *) oatNew(sizeof(SuccessorBlockInfo), - false); + (SuccessorBlockInfo *) oatNew(sizeof(SuccessorBlockInfo), + false); successorBlockInfo->block = catchBlock; - successorBlockInfo->key = handler->typeIdx; + successorBlockInfo->key = iterator.Get().type_idx_; oatInsertGrowableList(&curBlock->successorBlockList.blocks, (intptr_t) successorBlockInfo); oatSetBit(catchBlock->predecessors, curBlock->id); @@ -691,7 +663,6 @@ static void processCanThrow(CompilationUnit* cUnit, BasicBlock* curBlock, } } } -#endif } /* @@ -724,8 +695,8 @@ bool oatCompileMethod(Method* method, art::InstructionSet insnSet) cUnit.insnsSize = code_item->insns_size_; #if 1 // TODO: Use command-line argument passing mechanism - cUnit.printMe = true; - cUnit.printMeVerbose = true; + cUnit.printMe = false; + cUnit.printMeVerbose = false; cUnit.disableOpt = 0 | (1 << kLoadStoreElimination) | (1 << kLoadHoisting) | diff --git a/src/compiler/Ralloc.cc b/src/compiler/Ralloc.cc index 6a4e663e7d..8bbf659041 100644 --- a/src/compiler/Ralloc.cc +++ b/src/compiler/Ralloc.cc @@ -90,12 +90,66 @@ void oatSimpleRegAlloc(CompilationUnit* cUnit) GrowableListIterator iterator; oatGrowableListIteratorInit(&cUnit->blockList, &iterator); + /* Do type inference pass */ while (true) { BasicBlock *bb = (BasicBlock *) oatGrowableListIteratorNext(&iterator); if (bb == NULL) break; inferTypes(cUnit, bb); } + /* Add types of incoming arguments based on signature */ + int numRegs = cUnit->method->NumRegisters(); + int numIns = cUnit->method->NumIns(); + if (numIns > 0) { + int sReg = numRegs - numIns; + if (!cUnit->method->IsStatic()) { + // Skip past "this" + sReg++; + } + const art::StringPiece& shorty = cUnit->method->GetShorty(); + for (int i = 1; i < shorty.size(); i++) { + char arg = shorty[i]; + // Is it wide? + if ((arg == 'D') || (arg == 'J')) { + cUnit->regLocation[sReg].wide = true; + cUnit->regLocation[sReg+1].fp = cUnit->regLocation[sReg].fp; + sReg++; // Skip to next + } + sReg++; + } + } + + /* Mark wide use/defs */ + oatGrowableListIteratorInit(&cUnit->blockList, &iterator); + + /* Do size inference pass */ + while (true) { + BasicBlock *bb = (BasicBlock *) oatGrowableListIteratorNext(&iterator); + if (bb == NULL) break; + for (MIR* mir = bb->firstMIRInsn; mir; mir = mir->next) { + SSARepresentation* ssaRep = mir->ssaRep; + if (ssaRep == NULL) { + continue; + } + // TODO: special formats? + int attrs = oatDataFlowAttributes[mir->dalvikInsn.opcode]; + int next = 0; + if (attrs & DF_DA_WIDE) { + cUnit->regLocation[ssaRep->defs[0]].wide = true; + } + if (attrs & DF_UA_WIDE) { + cUnit->regLocation[ssaRep->uses[next]].wide = true; + next += 2; + } + if (attrs & DF_UB_WIDE) { + cUnit->regLocation[ssaRep->uses[next]].wide = true; + next += 2; + } + if (attrs & DF_UC_WIDE) { + cUnit->regLocation[ssaRep->uses[next]].wide = true; + } + } + } /* * Set the sRegLow field to refer to the pre-SSA name of the diff --git a/src/compiler/codegen/Ralloc.h b/src/compiler/codegen/Ralloc.h index b73ae3078f..c702204155 100644 --- a/src/compiler/codegen/Ralloc.h +++ b/src/compiler/codegen/Ralloc.h @@ -132,6 +132,7 @@ extern RegLocation oatGetDestWide(CompilationUnit* cUnit, MIR* mir, int low, int high); // Get the LocRecord associated with an SSA name use. extern RegLocation oatGetSrc(CompilationUnit* cUnit, MIR* mir, int num); +extern RegLocation oatGetRawSrc(CompilationUnit* cUnit, MIR* mir, int num); // Get the LocRecord associated with an SSA name def. extern RegLocation oatGetDest(CompilationUnit* cUnit, MIR* mir, int num); diff --git a/src/compiler/codegen/RallocUtil.cc b/src/compiler/codegen/RallocUtil.cc index 6a9777ebe2..d6e0bbc7bc 100644 --- a/src/compiler/codegen/RallocUtil.cc +++ b/src/compiler/codegen/RallocUtil.cc @@ -1000,24 +1000,56 @@ extern RegLocation oatEvalLoc(CompilationUnit* cUnit, RegLocation loc, return loc; } +/* + * There's currently a problem in SSA renaming. So long as register promotion + * is disabled, a bad renaming will have no effect. Work around the problem + * here to make progress while the fix is being identified. + */ +#define SSA_WORKAROUND + extern RegLocation oatGetDest(CompilationUnit* cUnit, MIR* mir, int num) { - return cUnit->regLocation[mir->ssaRep->defs[num]]; + RegLocation res = cUnit->regLocation[mir->ssaRep->defs[num]]; +#ifdef SSA_WORKAROUND + res.wide = false; +#endif + assert(!res.wide); + return res; } extern RegLocation oatGetSrc(CompilationUnit* cUnit, MIR* mir, int num) { - return cUnit->regLocation[mir->ssaRep->uses[num]]; + RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]]; +#ifdef SSA_WORKAROUND + res.wide = false; +#endif + assert(!res.wide); + return res; +} +extern RegLocation oatGetRawSrc(CompilationUnit* cUnit, MIR* mir, int num) +{ + RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]]; + return res; } extern RegLocation oatGetDestWide(CompilationUnit* cUnit, MIR* mir, int low, int high) { - return oatGetDest(cUnit, mir, low); + RegLocation res = cUnit->regLocation[mir->ssaRep->defs[low]]; +#ifdef SSA_WORKAROUND + res.wide = true; +#endif + assert(res.wide); + return res; } extern RegLocation oatGetSrcWide(CompilationUnit* cUnit, MIR* mir, int low, int high) { - return oatGetSrc(cUnit, mir, low); + RegLocation res = cUnit->regLocation[mir->ssaRep->uses[low]]; +#ifdef SSA_WORKAROUND + res.wide = true; +#endif + assert(res.wide); + return res; } /* Kill the corresponding bit in the null-checked register list */ diff --git a/src/compiler/codegen/arm/ArchFactory.cc b/src/compiler/codegen/arm/ArchFactory.cc index 243871910a..574bb57018 100644 --- a/src/compiler/codegen/arm/ArchFactory.cc +++ b/src/compiler/codegen/arm/ArchFactory.cc @@ -78,7 +78,10 @@ static TGT_LIR* genNullCheck(CompilationUnit* cUnit, int sReg, int mReg, int dOffset, TGT_LIR* pcrLabel) { /* This particular Dalvik register has been null-checked */ +#if 0 + // Yes, I know. Please be quiet. UNIMPLEMENTED(WARNING) << "Need null check & throw support"; +#endif return pcrLabel; if (oatIsBitSet(cUnit->regPool->nullCheckedRegs, sReg)) { return pcrLabel; diff --git a/src/compiler/codegen/arm/ArmRallocUtil.cc b/src/compiler/codegen/arm/ArmRallocUtil.cc index 78d5267c61..bea85ea8e8 100644 --- a/src/compiler/codegen/arm/ArmRallocUtil.cc +++ b/src/compiler/codegen/arm/ArmRallocUtil.cc @@ -35,10 +35,7 @@ typedef struct RefCounts { bool doubleStart; // Starting vReg for a double } RefCounts; -/* - * USE SSA names to count references of base Dalvik vRegs. Also, - * mark "wide" in the first of wide SSA locationRec pairs. - */ +/* USE SSA names to count references of base Dalvik vRegs. */ static void countRefs(CompilationUnit *cUnit, BasicBlock* bb, RefCounts* counts, bool fp) { @@ -61,16 +58,12 @@ static void countRefs(CompilationUnit *cUnit, BasicBlock* bb, oatConvertSSARegToDalvik(cUnit, ssaRep->defs[0])); counts[sReg].doubleStart = true; } - if (attrs & DF_DA_WIDE) { - cUnit->regLocation[ssaRep->defs[0]].wide = true; - } if ((attrs & (DF_UA_WIDE|DF_FP_A)) == (DF_UA_WIDE|DF_FP_A)) { sReg = DECODE_REG( oatConvertSSARegToDalvik(cUnit, ssaRep->uses[first])); counts[sReg].doubleStart = true; } if (attrs & DF_UA_WIDE) { - cUnit->regLocation[ssaRep->uses[first]].wide = true; first += 2; } if ((attrs & (DF_UB_WIDE|DF_FP_B)) == (DF_UB_WIDE|DF_FP_B)) { @@ -79,7 +72,6 @@ static void countRefs(CompilationUnit *cUnit, BasicBlock* bb, counts[sReg].doubleStart = true; } if (attrs & DF_UB_WIDE) { - cUnit->regLocation[ssaRep->uses[first]].wide = true; first += 2; } if ((attrs & (DF_UC_WIDE|DF_FP_C)) == (DF_UC_WIDE|DF_FP_C)) { @@ -87,9 +79,6 @@ static void countRefs(CompilationUnit *cUnit, BasicBlock* bb, oatConvertSSARegToDalvik(cUnit, ssaRep->uses[first])); counts[sReg].doubleStart = true; } - if (attrs & DF_UC_WIDE) { - cUnit->regLocation[ssaRep->uses[first]].wide = true; - } } for (i=0; i< ssaRep->numUses; i++) { int origSreg = DECODE_REG( @@ -140,27 +129,8 @@ static void dumpCounts(const RefCounts* arr, int size, const char* msg) extern void oatDoPromotion(CompilationUnit* cUnit) { int numRegs = cUnit->method->NumRegisters(); - int numIns = cUnit->method->NumIns(); /* - * Because ins don't have explicit definitions, we need to type - * them based on the signature. - */ - if (numIns > 0) { - int sReg = numRegs - numIns; - const art::StringPiece& shorty = cUnit->method->GetShorty(); - for (int i = 1; i < shorty.size(); i++) { - char arg = shorty[i]; - // Is it wide? - if ((arg == 'D') || (arg == 'J')) { - cUnit->regLocation[sReg].wide = true; - cUnit->regLocation[sReg+1].fp = cUnit->regLocation[sReg].fp; - sReg++; // Skip to next - } - sReg++; - } - } - /* * TUNING: is leaf? Can't just use "hasInvoke" to determine as some * instructions might call out to C/assembly helper functions. Until * machinery is in place, always spill lr. diff --git a/src/compiler/codegen/arm/MethodCodegenDriver.cc b/src/compiler/codegen/arm/MethodCodegenDriver.cc index b5ce6ea467..13e5497798 100644 --- a/src/compiler/codegen/arm/MethodCodegenDriver.cc +++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc @@ -14,6 +14,8 @@ * limitations under the License. */ +#define FORCE_SLOW 1 + static const RegLocation badLoc = {kLocDalvikFrame, 0, 0, INVALID_REG, INVALID_REG, INVALID_SREG, 0, kLocDalvikFrame, INVALID_REG, INVALID_REG, @@ -200,7 +202,7 @@ static void genSputWide(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) { int fieldIdx = mir->dalvikInsn.vB; Field* field = cUnit->method->GetDexCacheResolvedFields()->Get(fieldIdx); - if (field == NULL) { + if (FORCE_SLOW || field == NULL) { oatFlushAllRegs(cUnit); loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pSet64Static), rLR); loadConstant(cUnit, r0, mir->dalvikInsn.vB); @@ -256,7 +258,7 @@ static void genSgetWide(CompilationUnit* cUnit, MIR* mir, { int fieldIdx = mir->dalvikInsn.vB; Field* field = cUnit->method->GetDexCacheResolvedFields()->Get(fieldIdx); - if (field == NULL) { + if (FORCE_SLOW || field == NULL) { oatFlushAllRegs(cUnit); loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pGet64Static), rLR); loadConstant(cUnit, r0, mir->dalvikInsn.vB); @@ -314,7 +316,7 @@ static void genSget(CompilationUnit* cUnit, MIR* mir, Field* field = cUnit->method->GetDexCacheResolvedFields()->Get(fieldIdx); bool isObject = ((mir->dalvikInsn.opcode == OP_SGET_OBJECT) || (mir->dalvikInsn.opcode == OP_SGET_OBJECT_VOLATILE)); - if (field == NULL) { + if (FORCE_SLOW || field == NULL) { // Slow path int funcOffset = isObject ? OFFSETOF_MEMBER(Thread, pGetObjStatic) : OFFSETOF_MEMBER(Thread, pGet32Static); @@ -527,8 +529,8 @@ static int loadArgRegs(CompilationUnit* cUnit, MIR* mir, { for (int i = 0; i < 3; i++) { if (args[i] != INVALID_REG) { - RegLocation rlArg = oatGetSrc(cUnit, mir, i); // Arguments are treated as a series of untyped 32-bit values. + RegLocation rlArg = oatGetRawSrc(cUnit, mir, i); rlArg.wide = false; loadValueDirectFixed(cUnit, rlArg, r1 + i); callState = nextCallInsn(cUnit, mir, dInsn, callState, rollback); @@ -709,6 +711,8 @@ static int genDalvikArgsNoRange(CompilationUnit* cUnit, MIR* mir, RegLocation rlArg; int registerArgs[3]; +skipThis = false; + /* If no arguments, just return */ if (dInsn->vA == 0) return callState; @@ -722,8 +726,7 @@ static int genDalvikArgsNoRange(CompilationUnit* cUnit, MIR* mir, */ for (unsigned int i=3; i < dInsn->vA; i++) { int reg; - int arg = (isRange) ? dInsn->vC + i : i; - rlArg = oatUpdateLoc(cUnit, oatGetSrc(cUnit, mir, arg)); + rlArg = oatUpdateLoc(cUnit, oatGetSrc(cUnit, mir, i)); if (rlArg.location == kLocPhysReg) { reg = rlArg.lowReg; } else { @@ -736,12 +739,15 @@ static int genDalvikArgsNoRange(CompilationUnit* cUnit, MIR* mir, } /* Load register arguments r1..r3 */ - for (unsigned int i = skipThis ? 1 : 0; i < 3; i++) { + for (unsigned int i = 0; i < 3; i++) { if (i < dInsn->vA) registerArgs[i] = (isRange) ? dInsn->vC + i : i; else registerArgs[i] = INVALID_REG; } + if (skipThis) { + registerArgs[0] = INVALID_REG; + } callState = loadArgRegs(cUnit, mir, dInsn, callState, registerArgs, nextCallInsn, rollback); @@ -775,6 +781,9 @@ static int genDalvikArgsRange(CompilationUnit* cUnit, MIR* mir, { int firstArg = dInsn->vC; int numArgs = dInsn->vA; + int registerArgs[3]; + +skipThis = false; // If we can treat it as non-range (Jumbo ops will use range form) if (numArgs <= 5) @@ -798,7 +807,7 @@ static int genDalvikArgsRange(CompilationUnit* cUnit, MIR* mir, */ // Scan the rest of the args - if in physReg flush to memory for (int i = 4; i < numArgs; i++) { - RegLocation loc = oatGetSrc(cUnit, mir, i); + RegLocation loc = oatGetRawSrc(cUnit, mir, i); if (loc.wide) { loc = oatUpdateLocWide(cUnit, loc); if (loc.location == kLocPhysReg) { // TUNING: if dirty? @@ -840,11 +849,17 @@ static int genDalvikArgsRange(CompilationUnit* cUnit, MIR* mir, } // Handle the 1st 3 in r1, r2 & r3 - for (unsigned int i = skipThis? 1 : 0; i < dInsn->vA && i < 3; i++) { - RegLocation loc = oatGetSrc(cUnit, mir, firstArg + i); - loadValueDirectFixed(cUnit, loc, r1 + i); - callState = nextCallInsn(cUnit, mir, dInsn, callState, rollback); + for (unsigned int i = 0; i < 3; i++) { + if (i < dInsn->vA) + registerArgs[i] = dInsn->vC + i; + else + registerArgs[i] = INVALID_REG; } + if (skipThis) { + registerArgs[0] = INVALID_REG; + } + callState = loadArgRegs(cUnit, mir, dInsn, callState, registerArgs, + nextCallInsn, rollback); // Finally, deal with the register arguments // We'll be using fixed registers here @@ -958,9 +973,7 @@ static void genInvokeVirtual(CompilationUnit* cUnit, MIR* mir) Get(dInsn->vB); NextCallInsn nextCallInsn; - method = NULL; // TODO - UNIMPLEMENTED(WARNING) << "the genInvokeVirtual fast path generates bad code (r0/r9 mixup?)"; - if (method == NULL) { + if (FORCE_SLOW || method == NULL) { // Slow path nextCallInsn = nextVCallInsnSP; // If we need a slow-path callout, we'll restart here diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc index 9ea9e705d1..b9e135c3ed 100644 --- a/src/compiler/codegen/arm/Thumb2/Gen.cc +++ b/src/compiler/codegen/arm/Thumb2/Gen.cc @@ -1232,6 +1232,7 @@ static void genArrayGet(CompilationUnit* cUnit, MIR* mir, OpSize size, /* regPtr -> array data */ opRegRegImm(cUnit, kOpAdd, regPtr, rlArray.lowReg, dataOffset); } + oatFreeTemp(cUnit, rlArray.lowReg); if ((size == kLong) || (size == kDouble)) { if (scale) { int rNewIndex = oatAllocTemp(cUnit); @@ -1241,6 +1242,7 @@ static void genArrayGet(CompilationUnit* cUnit, MIR* mir, OpSize size, } else { opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg); } + oatFreeTemp(cUnit, rlIndex.lowReg); rlResult = oatEvalLoc(cUnit, rlDest, regClass, true); loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg); diff --git a/src/compiler_test.cc b/src/compiler_test.cc index e3ff47f095..cc5c6bcf7a 100644 --- a/src/compiler_test.cc +++ b/src/compiler_test.cc @@ -135,6 +135,13 @@ TEST_F(CompilerTest, DISABLED_CatchTest) { 1000); } +TEST_F(CompilerTest, CatchTestNoThrow) { + CompileDirectMethod(NULL, "java.lang.Object", "<init>", "()V"); + const ClassLoader* class_loader = LoadDex("IntMath"); + AssertStaticIntMethod(class_loader, "IntMath", "catchBlockNoThrow", "(I)I", + 1123, 1000); +} + TEST_F(CompilerTest, StaticFieldTest) { AssertStaticIntMethod(LoadDex("IntMath"), "IntMath", "staticFieldTest", "(I)I", 1404, 404); diff --git a/test/IntMath/IntMath.java b/test/IntMath/IntMath.java index 1be8a98b0f..14c68d1447 100644 --- a/test/IntMath/IntMath.java +++ b/test/IntMath/IntMath.java @@ -67,6 +67,15 @@ class IntMath extends IntMathBase { return x; } + static int catchBlockNoThrow(int x) { + try { + x += 123; + } catch (NullPointerException npe) { + x += 456; + } + return x; + } + static int staticFieldTest(int x) { mBoolean1 = true; mBoolean2 = false; @@ -627,20 +636,14 @@ class IntMath extends IntMathBase { } } - /* - static void throwNullPointerException() { - throw new NullPointerException("first throw"); - } - - static int throwAndCatch() { + static int throwAndCatch() { try { - throwNullPointerException(); - return 1; + throwNullPointerException(); + return 1; } catch (NullPointerException npe) { - return 0; - } + return 0; } - */ + } static int manyArgs(int a0, long a1, int a2, long a3, int a4, long a5, int a6, int a7, double a8, float a9, double a10, short a11, int a12, @@ -807,14 +810,12 @@ class IntMath extends IntMathBase { System.out.println("fibonacci FAILED: " + res); } - /* - res = throwAndCatch(); - if (res == 0) { + res = throwAndCatch(); + if (res == 0) { System.out.println("throwAndCatch PASSED"); - } else { + } else { System.out.println("throwAndCatch FAILED: " + res); - } - */ + } res = manyArgs(0, 1L, 2, 3L, 4, 5L, 6, 7, 8.0, 9.0f, 10.0, (short)11, 12, (char)13, 14, 15, (byte)-16, true, 18, @@ -853,6 +854,13 @@ class IntMath extends IntMathBase { System.out.println("catchBlock FAILED: " + res); } + res = catchBlockNoThrow(1000); + if (res == 1123) { + System.out.println("catchBlockNoThrow PASSED"); + } else { + System.out.println("catchBlockNoThrow FAILED: " + res); + } + res = superTest(4141); if (res == 4175) { System.out.println("superTest PASSED"); |