Try/Catch analysis; various workarounds

Fixed a couple of codegen bugs.  Added a temporary workaround until
SSA renaming problem is fixed.  By enabling the "CompileDexLibCore"
test in compiler_test.cc and disabling the jni_compiler, we appear to
be successfully compiling 17,641 methods of libcore (note: of those,
4 exhibit the SSA problem).

Also turned off most of the compiler logging, and disabled the fast
path for invoke virtual (which seems to be broken).

Change-Id: I0ecf460cba209f885209efbee62e9f80bffbf666
diff --git a/src/compiler.cc b/src/compiler.cc
index e2d72f5..4e3c052 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -128,7 +128,7 @@
   } 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 64d701e..8488606 100644
--- a/src/compiler/Frontend.cc
+++ b/src/compiler/Frontend.cc
@@ -394,63 +394,44 @@
 /* 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 @@
                             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;
+        art::DexFile::CatchHandlerIterator iterator =
+            art::DexFile::dexFindCatchHandler(*code_item, curOffset);
 
-        if (!dexFindCatchHandler(&iterator, dexCode, curOffset)) {
-            LOG(FATAL) << "Catch block not found in dexfile for insn " <<
-                curOffset << " in " << method->name;
-
-        }
         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 @@
             }
         }
     }
-#endif
 }
 
 /*
@@ -724,8 +695,8 @@
     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 6a4e663..8bbf659 100644
--- a/src/compiler/Ralloc.cc
+++ b/src/compiler/Ralloc.cc
@@ -90,12 +90,66 @@
     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 b73ae30..c702204 100644
--- a/src/compiler/codegen/Ralloc.h
+++ b/src/compiler/codegen/Ralloc.h
@@ -132,6 +132,7 @@
                                   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 6a9777e..d6e0bbc 100644
--- a/src/compiler/codegen/RallocUtil.cc
+++ b/src/compiler/codegen/RallocUtil.cc
@@ -1000,24 +1000,56 @@
     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 2438719..574bb57 100644
--- a/src/compiler/codegen/arm/ArchFactory.cc
+++ b/src/compiler/codegen/arm/ArchFactory.cc
@@ -78,7 +78,10 @@
                              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 78d5267..bea85ea 100644
--- a/src/compiler/codegen/arm/ArmRallocUtil.cc
+++ b/src/compiler/codegen/arm/ArmRallocUtil.cc
@@ -35,10 +35,7 @@
     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 @@
                         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 @@
                     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 @@
                         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 @@
 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 b5ce6ea..13e5497 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 @@
 {
     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 @@
 {
     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 @@
     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 @@
 {
     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 @@
     RegLocation rlArg;
     int registerArgs[3];
 
+skipThis = false;
+
     /* If no arguments, just return */
     if (dInsn->vA == 0)
         return callState;
@@ -722,8 +726,7 @@
      */
     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 @@
     }
 
     /* 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 @@
 {
     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 @@
      */
     // 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 @@
     }
 
     // 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 @@
         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 9ea9e70..b9e135c 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -1232,6 +1232,7 @@
         /* 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 @@
         } 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 e3ff47f..cc5c6bc 100644
--- a/src/compiler_test.cc
+++ b/src/compiler_test.cc
@@ -135,6 +135,13 @@
                         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);