Prune useless entries from dex to pc map

Step one of the change.  Limit entries in the table to native
code safepoint locations (which generally are the return PC
addresses of any call that might trigger a stack walk and the
start addresses of all catch blocks).

Previously, the mapping_table described ranges.  No longer.  Any
native PC located within compiled Dex code that is found in a
stack walk should have an exact match in the table.

In future CLs we'll add data compression (probably uLeb128) and
may add inflation on first use to a faster access map (instead of
the current linear search).

Note that this CL introduces somewhat of a regression in the
capabilities of oat-dump.  Because the mapping table no longer
associates each native intruction with its Dex counter-part, the
native code disassembly no longer includes interspersed Dex
disassembly.

Note also that as of this CL, the compiler is adopting the 100-char
line length limit used in the rest of Art.  The 80-char limit
should still be used in any code that we expect to upstream to
llvm.

Change-Id: I1beca4d57c41e8161bf746bc62abbce08d5bcb4d
diff --git a/src/compiler/codegen/CodegenUtil.cc b/src/compiler/codegen/CodegenUtil.cc
index bdc2c8b..dff30be 100644
--- a/src/compiler/codegen/CodegenUtil.cc
+++ b/src/compiler/codegen/CodegenUtil.cc
@@ -334,6 +334,9 @@
     case kPseudoSuspendTarget:
       LOG(INFO) << "LS" << (void*)lir << ":";
       break;
+    case kPseudoSafepointPC:
+      LOG(INFO) << "LsafepointPC_0x" << std::hex << lir->offset << "_" << lir->dalvikOffset << ":";
+      break;
     case kPseudoCaseLabel:
       LOG(INFO) << "LC" << (void*)lir << ": Case target 0x"
                 << std::hex << lir->operands[0] << "|" << std::dec <<
@@ -465,9 +468,9 @@
   insn->operands[4] = op4;
   insn->target = target;
   oatSetupResourceMasks(insn);
-  if (opcode == kPseudoTargetLabel) {
+  if ((opcode == kPseudoTargetLabel) || (opcode == kPseudoSafepointPC)) {
     // Always make labels scheduling barriers
-    insn->defMask = ENCODE_ALL;
+    insn->useMask = insn->defMask = ENCODE_ALL;
   }
   return insn;
 }
@@ -757,18 +760,10 @@
 
 void createMappingTable(CompilationUnit* cUnit)
 {
-  LIR* tgtLIR;
-  int currentDalvikOffset = -1;
-
-  for (tgtLIR = (LIR *) cUnit->firstLIRInsn;
-     tgtLIR;
-     tgtLIR = NEXT_LIR(tgtLIR)) {
-    if ((tgtLIR->opcode >= 0) && !tgtLIR->flags.isNop &&
-      (currentDalvikOffset != tgtLIR->dalvikOffset)) {
-      // Changed - need to emit a record
+  for (LIR* tgtLIR = (LIR *) cUnit->firstLIRInsn; tgtLIR != NULL; tgtLIR = NEXT_LIR(tgtLIR)) {
+    if (!tgtLIR->flags.isNop && (tgtLIR->opcode == kPseudoSafepointPC)) {
       cUnit->mappingTable.push_back(tgtLIR->offset);
       cUnit->mappingTable.push_back(tgtLIR->dalvikOffset);
-      currentDalvikOffset = tgtLIR->dalvikOffset;
     }
   }
 }
diff --git a/src/compiler/codegen/GenCommon.cc b/src/compiler/codegen/GenCommon.cc
index 8c431f5..5593151 100644
--- a/src/compiler/codegen/GenCommon.cc
+++ b/src/compiler/codegen/GenCommon.cc
@@ -30,36 +30,49 @@
                         RegLocation rlSrc, RegLocation rlDest, int lit);
 #endif
 
-void callRuntimeHelperImm(CompilationUnit* cUnit, int helperOffset, int arg0) {
+void markSafepointPC(CompilationUnit* cUnit, LIR* inst)
+{
+  inst->defMask = ENCODE_ALL;
+  LIR* safepointPC = newLIR0(cUnit, kPseudoSafepointPC);
+  DCHECK_EQ(safepointPC->defMask, ENCODE_ALL);
+}
+
+void callRuntimeHelperImm(CompilationUnit* cUnit, int helperOffset, int arg0, bool safepointPC) {
 #if !defined(TARGET_X86)
   int rTgt = loadHelper(cUnit, helperOffset);
 #endif
   loadConstant(cUnit, rARG0, arg0);
   oatClobberCalleeSave(cUnit);
 #if !defined(TARGET_X86)
-  opReg(cUnit, kOpBlx, rTgt);
+  LIR* callInst = opReg(cUnit, kOpBlx, rTgt);
   oatFreeTemp(cUnit, rTgt);
 #else
-  opThreadMem(cUnit, kOpBlx, helperOffset);
+  LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset);
 #endif
+  if (safepointPC) {
+    markSafepointPC(cUnit, callInst);
+  }
 }
 
-void callRuntimeHelperReg(CompilationUnit* cUnit, int helperOffset, int arg0) {
+void callRuntimeHelperReg(CompilationUnit* cUnit, int helperOffset, int arg0, bool safepointPC) {
 #if !defined(TARGET_X86)
   int rTgt = loadHelper(cUnit, helperOffset);
 #endif
   opRegCopy(cUnit, rARG0, arg0);
   oatClobberCalleeSave(cUnit);
 #if !defined(TARGET_X86)
-  opReg(cUnit, kOpBlx, rTgt);
+  LIR* callInst = opReg(cUnit, kOpBlx, rTgt);
   oatFreeTemp(cUnit, rTgt);
 #else
-  opThreadMem(cUnit, kOpBlx, helperOffset);
+  LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset);
 #endif
+  if (safepointPC) {
+    markSafepointPC(cUnit, callInst);
+  }
 }
 
-void callRuntimeHelperRegLocation(CompilationUnit* cUnit, int helperOffset,
-                                  RegLocation arg0) {
+void callRuntimeHelperRegLocation(CompilationUnit* cUnit, int helperOffset, RegLocation arg0,
+                                  bool safepointPC) {
 #if !defined(TARGET_X86)
   int rTgt = loadHelper(cUnit, helperOffset);
 #endif
@@ -70,15 +83,18 @@
   }
   oatClobberCalleeSave(cUnit);
 #if !defined(TARGET_X86)
-  opReg(cUnit, kOpBlx, rTgt);
+  LIR* callInst = opReg(cUnit, kOpBlx, rTgt);
   oatFreeTemp(cUnit, rTgt);
 #else
-  opThreadMem(cUnit, kOpBlx, helperOffset);
+  LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset);
 #endif
+  if (safepointPC) {
+    markSafepointPC(cUnit, callInst);
+  }
 }
 
-void callRuntimeHelperImmImm(CompilationUnit* cUnit, int helperOffset,
-                             int arg0, int arg1) {
+void callRuntimeHelperImmImm(CompilationUnit* cUnit, int helperOffset, int arg0, int arg1,
+                             bool safepointPC) {
 #if !defined(TARGET_X86)
   int rTgt = loadHelper(cUnit, helperOffset);
 #endif
@@ -86,15 +102,18 @@
   loadConstant(cUnit, rARG1, arg1);
   oatClobberCalleeSave(cUnit);
 #if !defined(TARGET_X86)
-  opReg(cUnit, kOpBlx, rTgt);
+  LIR* callInst = opReg(cUnit, kOpBlx, rTgt);
   oatFreeTemp(cUnit, rTgt);
 #else
-  opThreadMem(cUnit, kOpBlx, helperOffset);
+  LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset);
 #endif
+  if (safepointPC) {
+    markSafepointPC(cUnit, callInst);
+  }
 }
 
-void callRuntimeHelperImmRegLocation(CompilationUnit* cUnit, int helperOffset,
-                                     int arg0, RegLocation arg1) {
+void callRuntimeHelperImmRegLocation(CompilationUnit* cUnit, int helperOffset, int arg0,
+                                     RegLocation arg1, bool safepointPC) {
 #if !defined(TARGET_X86)
   int rTgt = loadHelper(cUnit, helperOffset);
 #endif
@@ -106,15 +125,18 @@
   loadConstant(cUnit, rARG0, arg0);
   oatClobberCalleeSave(cUnit);
 #if !defined(TARGET_X86)
-  opReg(cUnit, kOpBlx, rTgt);
+  LIR* callInst = opReg(cUnit, kOpBlx, rTgt);
   oatFreeTemp(cUnit, rTgt);
 #else
-  opThreadMem(cUnit, kOpBlx, helperOffset);
+  LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset);
 #endif
+  if (safepointPC) {
+    markSafepointPC(cUnit, callInst);
+  }
 }
 
-void callRuntimeHelperRegLocationImm(CompilationUnit* cUnit, int helperOffset,
-                                     RegLocation arg0, int arg1) {
+void callRuntimeHelperRegLocationImm(CompilationUnit* cUnit, int helperOffset, RegLocation arg0,
+                                     int arg1, bool safepointPC) {
 #if !defined(TARGET_X86)
   int rTgt = loadHelper(cUnit, helperOffset);
 #endif
@@ -122,15 +144,18 @@
   loadConstant(cUnit, rARG1, arg1);
   oatClobberCalleeSave(cUnit);
 #if !defined(TARGET_X86)
-  opReg(cUnit, kOpBlx, rTgt);
+  LIR* callInst = opReg(cUnit, kOpBlx, rTgt);
   oatFreeTemp(cUnit, rTgt);
 #else
-  opThreadMem(cUnit, kOpBlx, helperOffset);
+  LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset);
 #endif
+  if (safepointPC) {
+    markSafepointPC(cUnit, callInst);
+  }
 }
 
-void callRuntimeHelperImmReg(CompilationUnit* cUnit, int helperOffset,
-                             int arg0, int arg1) {
+void callRuntimeHelperImmReg(CompilationUnit* cUnit, int helperOffset, int arg0, int arg1,
+                             bool safepointPC) {
 #if !defined(TARGET_X86)
   int rTgt = loadHelper(cUnit, helperOffset);
 #endif
@@ -138,15 +163,18 @@
   loadConstant(cUnit, rARG0, arg0);
   oatClobberCalleeSave(cUnit);
 #if !defined(TARGET_X86)
-  opReg(cUnit, kOpBlx, rTgt);
+  LIR* callInst = opReg(cUnit, kOpBlx, rTgt);
   oatFreeTemp(cUnit, rTgt);
 #else
-  opThreadMem(cUnit, kOpBlx, helperOffset);
+  LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset);
 #endif
+  if (safepointPC) {
+    markSafepointPC(cUnit, callInst);
+  }
 }
 
-void callRuntimeHelperRegImm(CompilationUnit* cUnit, int helperOffset,
-                             int arg0, int arg1) {
+void callRuntimeHelperRegImm(CompilationUnit* cUnit, int helperOffset, int arg0, int arg1,
+                             bool safepointPC) {
 #if !defined(TARGET_X86)
   int rTgt = loadHelper(cUnit, helperOffset);
 #endif
@@ -154,15 +182,17 @@
   loadConstant(cUnit, rARG1, arg1);
   oatClobberCalleeSave(cUnit);
 #if !defined(TARGET_X86)
-  opReg(cUnit, kOpBlx, rTgt);
+  LIR* callInst = opReg(cUnit, kOpBlx, rTgt);
   oatFreeTemp(cUnit, rTgt);
 #else
-  opThreadMem(cUnit, kOpBlx, helperOffset);
+  LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset);
 #endif
+  if (safepointPC) {
+    markSafepointPC(cUnit, callInst);
+  }
 }
 
-void callRuntimeHelperImmMethod(CompilationUnit* cUnit, int helperOffset,
-                                int arg0) {
+void callRuntimeHelperImmMethod(CompilationUnit* cUnit, int helperOffset, int arg0, bool safepointPC) {
 #if !defined(TARGET_X86)
   int rTgt = loadHelper(cUnit, helperOffset);
 #endif
@@ -170,17 +200,18 @@
   loadConstant(cUnit, rARG0, arg0);
   oatClobberCalleeSave(cUnit);
 #if !defined(TARGET_X86)
-  opReg(cUnit, kOpBlx, rTgt);
+  LIR* callInst = opReg(cUnit, kOpBlx, rTgt);
   oatFreeTemp(cUnit, rTgt);
 #else
-  opThreadMem(cUnit, kOpBlx, helperOffset);
+  LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset);
 #endif
+  if (safepointPC) {
+    markSafepointPC(cUnit, callInst);
+  }
 }
 
-void callRuntimeHelperRegLocationRegLocation(CompilationUnit* cUnit,
-                                             int helperOffset,
-                                             RegLocation arg0,
-                                             RegLocation arg1) {
+void callRuntimeHelperRegLocationRegLocation(CompilationUnit* cUnit, int helperOffset,
+                                             RegLocation arg0, RegLocation arg1, bool safepointPC) {
 #if !defined(TARGET_X86)
   int rTgt = loadHelper(cUnit, helperOffset);
 #endif
@@ -201,15 +232,18 @@
   }
   oatClobberCalleeSave(cUnit);
 #if !defined(TARGET_X86)
-  opReg(cUnit, kOpBlx, rTgt);
+  LIR* callInst = opReg(cUnit, kOpBlx, rTgt);
   oatFreeTemp(cUnit, rTgt);
 #else
-  opThreadMem(cUnit, kOpBlx, helperOffset);
+  LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset);
 #endif
+  if (safepointPC) {
+    markSafepointPC(cUnit, callInst);
+  }
 }
 
-void callRuntimeHelperRegReg(CompilationUnit* cUnit, int helperOffset,
-                             int arg0, int arg1) {
+void callRuntimeHelperRegReg(CompilationUnit* cUnit, int helperOffset, int arg0, int arg1,
+                             bool safepointPC) {
 #if !defined(TARGET_X86)
   int rTgt = loadHelper(cUnit, helperOffset);
 #endif
@@ -218,15 +252,18 @@
   opRegCopy(cUnit, rARG1, arg1);
   oatClobberCalleeSave(cUnit);
 #if !defined(TARGET_X86)
-  opReg(cUnit, kOpBlx, rTgt);
+  LIR* callInst = opReg(cUnit, kOpBlx, rTgt);
   oatFreeTemp(cUnit, rTgt);
 #else
-  opThreadMem(cUnit, kOpBlx, helperOffset);
+  LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset);
 #endif
+  if (safepointPC) {
+    markSafepointPC(cUnit, callInst);
+  }
 }
 
-void callRuntimeHelperRegRegImm(CompilationUnit* cUnit, int helperOffset,
-                                int arg0, int arg1, int arg2) {
+void callRuntimeHelperRegRegImm(CompilationUnit* cUnit, int helperOffset, int arg0, int arg1,
+                                int arg2, bool safepointPC) {
 #if !defined(TARGET_X86)
   int rTgt = loadHelper(cUnit, helperOffset);
 #endif
@@ -236,16 +273,18 @@
   loadConstant(cUnit, rARG2, arg2);
   oatClobberCalleeSave(cUnit);
 #if !defined(TARGET_X86)
-  opReg(cUnit, kOpBlx, rTgt);
+  LIR* callInst = opReg(cUnit, kOpBlx, rTgt);
   oatFreeTemp(cUnit, rTgt);
 #else
-  opThreadMem(cUnit, kOpBlx, helperOffset);
+  LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset);
 #endif
+  if (safepointPC) {
+    markSafepointPC(cUnit, callInst);
+  }
 }
 
-void callRuntimeHelperImmMethodRegLocation(CompilationUnit* cUnit,
-                                           int helperOffset,
-                       int arg0, RegLocation arg2) {
+void callRuntimeHelperImmMethodRegLocation(CompilationUnit* cUnit, int helperOffset, int arg0,
+                                           RegLocation arg2, bool safepointPC) {
 #if !defined(TARGET_X86)
   int rTgt = loadHelper(cUnit, helperOffset);
 #endif
@@ -254,15 +293,18 @@
   loadConstant(cUnit, rARG0, arg0);
   oatClobberCalleeSave(cUnit);
 #if !defined(TARGET_X86)
-  opReg(cUnit, kOpBlx, rTgt);
+  LIR* callInst = opReg(cUnit, kOpBlx, rTgt);
   oatFreeTemp(cUnit, rTgt);
 #else
-  opThreadMem(cUnit, kOpBlx, helperOffset);
+  LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset);
 #endif
+  if (safepointPC) {
+    markSafepointPC(cUnit, callInst);
+  }
 }
 
-void callRuntimeHelperImmMethodImm(CompilationUnit* cUnit, int helperOffset,
-                                   int arg0, int arg2) {
+void callRuntimeHelperImmMethodImm(CompilationUnit* cUnit, int helperOffset, int arg0, int arg2,
+                                   bool safepointPC) {
 #if !defined(TARGET_X86)
   int rTgt = loadHelper(cUnit, helperOffset);
 #endif
@@ -271,17 +313,19 @@
   loadConstant(cUnit, rARG0, arg0);
   oatClobberCalleeSave(cUnit);
 #if !defined(TARGET_X86)
-  opReg(cUnit, kOpBlx, rTgt);
+  LIR* callInst = opReg(cUnit, kOpBlx, rTgt);
   oatFreeTemp(cUnit, rTgt);
 #else
-  opThreadMem(cUnit, kOpBlx, helperOffset);
+  LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset);
 #endif
+  if (safepointPC) {
+    markSafepointPC(cUnit, callInst);
+  }
 }
 
-void callRuntimeHelperImmRegLocationRegLocation(CompilationUnit* cUnit,
-                                                int helperOffset,
-                                                int arg0, RegLocation arg1,
-                                                RegLocation arg2) {
+void callRuntimeHelperImmRegLocationRegLocation(CompilationUnit* cUnit, int helperOffset,
+                                                int arg0, RegLocation arg1, RegLocation arg2,
+                                                bool safepointPC) {
 #if !defined(TARGET_X86)
   int rTgt = loadHelper(cUnit, helperOffset);
 #endif
@@ -294,11 +338,14 @@
   loadConstant(cUnit, rARG0, arg0);
   oatClobberCalleeSave(cUnit);
 #if !defined(TARGET_X86)
-  opReg(cUnit, kOpBlx, rTgt);
+  LIR* callInst = opReg(cUnit, kOpBlx, rTgt);
   oatFreeTemp(cUnit, rTgt);
 #else
-  opThreadMem(cUnit, kOpBlx, helperOffset);
+  LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset);
 #endif
+  if (safepointPC) {
+    markSafepointPC(cUnit, callInst);
+  }
 }
 
 /*
@@ -508,7 +555,7 @@
   } else {
     funcOffset= ENTRYPOINT_OFFSET(pAllocArrayFromCodeWithAccessCheck);
   }
-  callRuntimeHelperImmMethodRegLocation(cUnit, funcOffset, type_idx, rlSrc);
+  callRuntimeHelperImmMethodRegLocation(cUnit, funcOffset, type_idx, rlSrc, true);
   RegLocation rlResult = oatGetReturn(cUnit, false);
   storeValue(cUnit, rlDest, rlResult);
 }
@@ -532,7 +579,7 @@
   } else {
     funcOffset = ENTRYPOINT_OFFSET(pCheckAndAllocArrayFromCodeWithAccessCheck);
   }
-  callRuntimeHelperImmMethodImm(cUnit, funcOffset, typeIdx, elems);
+  callRuntimeHelperImmMethodImm(cUnit, funcOffset, typeIdx, elems, true);
   oatFreeTemp(cUnit, rARG2);
   oatFreeTemp(cUnit, rARG1);
   /*
@@ -679,9 +726,7 @@
       // TUNING: fast path should fall through
       LIR* branchOver = opCmpImmBranch(cUnit, kCondNe, rBase, 0, NULL);
       loadConstant(cUnit, rARG0, ssbIndex);
-      callRuntimeHelperImm(cUnit,
-                           ENTRYPOINT_OFFSET(pInitializeStaticStorage),
-                           ssbIndex);
+      callRuntimeHelperImm(cUnit, ENTRYPOINT_OFFSET(pInitializeStaticStorage), ssbIndex, true);
 #if defined(TARGET_MIPS)
       // For Arm, rRET0 = rARG0 = rBASE, for Mips, we need to copy
       opRegCopy(cUnit, rBase, rRET0);
@@ -718,7 +763,7 @@
     int setterOffset = isLongOrDouble ? ENTRYPOINT_OFFSET(pSet64Static) :
         (isObject ? ENTRYPOINT_OFFSET(pSetObjStatic)
         : ENTRYPOINT_OFFSET(pSet32Static));
-    callRuntimeHelperImmRegLocation(cUnit, setterOffset, fieldIdx, rlSrc);
+    callRuntimeHelperImmRegLocation(cUnit, setterOffset, fieldIdx, rlSrc, true);
   }
 }
 
@@ -772,8 +817,7 @@
       // or NULL if not initialized. Check for NULL and call helper if NULL.
       // TUNING: fast path should fall through
       LIR* branchOver = opCmpImmBranch(cUnit, kCondNe, rBase, 0, NULL);
-      callRuntimeHelperImm(cUnit, ENTRYPOINT_OFFSET(pInitializeStaticStorage),
-                           ssbIndex);
+      callRuntimeHelperImm(cUnit, ENTRYPOINT_OFFSET(pInitializeStaticStorage), ssbIndex, true);
 #if defined(TARGET_MIPS)
       // For Arm, rRET0 = rARG0 = rBASE, for Mips, we need to copy
       opRegCopy(cUnit, rBase, rRET0);
@@ -804,7 +848,7 @@
     int getterOffset = isLongOrDouble ? ENTRYPOINT_OFFSET(pGet64Static) :
         (isObject ? ENTRYPOINT_OFFSET(pGetObjStatic)
         : ENTRYPOINT_OFFSET(pGet32Static));
-    callRuntimeHelperImm(cUnit, getterOffset, fieldIdx);
+    callRuntimeHelperImm(cUnit, getterOffset, fieldIdx, true);
     if (isLongOrDouble) {
       RegLocation rlResult = oatGetReturnWide(cUnit, rlDest.fp);
       storeValueWide(cUnit, rlDest, rlResult);
@@ -841,11 +885,12 @@
     cUnit->currentDalvikOffset = lab->operands[1];
     oatAppendLIR(cUnit, lab);
 #if defined(TARGET_X86)
-    opThreadMem(cUnit, kOpBlx, ENTRYPOINT_OFFSET(pTestSuspendFromCode));
+    LIR* callInst = opThreadMem(cUnit, kOpBlx, ENTRYPOINT_OFFSET(pTestSuspendFromCode));
 #else
     int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pTestSuspendFromCode));
-    opReg(cUnit, kOpBlx, rTgt);
+    LIR* callInst = opReg(cUnit, kOpBlx, rTgt);
 #endif
+    markSafepointPC(cUnit, callInst);
     opUnconditionalBranch(cUnit, resumeLab);
   }
 }
@@ -861,6 +906,7 @@
     CallInfo* info = (CallInfo*)lab->operands[0];
     cUnit->currentDalvikOffset = info->offset;
     oatAppendLIR(cUnit, lab);
+    // NOTE: genInvoke handles markSafepointPC
     genInvoke(cUnit, info);
     LIR* resumeLab = (LIR*)lab->operands[2];
     if (resumeLab != NULL) {
@@ -943,11 +989,12 @@
     oatClobberCalleeSave(cUnit);
 #if !defined(TARGET_X86)
     int rTgt = loadHelper(cUnit, funcOffset);
-    opReg(cUnit, kOpBlx, rTgt);
+    LIR* callInst = opReg(cUnit, kOpBlx, rTgt);
     oatFreeTemp(cUnit, rTgt);
 #else
-    opThreadMem(cUnit, kOpBlx, funcOffset);
+    LIR* callInst = opThreadMem(cUnit, kOpBlx, funcOffset);
 #endif
+    markSafepointPC(cUnit, callInst);
   }
 }
 
@@ -1018,7 +1065,7 @@
     int getterOffset = isLongOrDouble ? ENTRYPOINT_OFFSET(pGet64Instance) :
         (isObject ? ENTRYPOINT_OFFSET(pGetObjInstance)
         : ENTRYPOINT_OFFSET(pGet32Instance));
-    callRuntimeHelperImmRegLocation(cUnit, getterOffset, fieldIdx, rlObj);
+    callRuntimeHelperImmRegLocation(cUnit, getterOffset, fieldIdx, rlObj, true);
     if (isLongOrDouble) {
       RegLocation rlResult = oatGetReturnWide(cUnit, rlDest.fp);
       storeValueWide(cUnit, rlDest, rlResult);
@@ -1073,8 +1120,7 @@
     int setterOffset = isLongOrDouble ? ENTRYPOINT_OFFSET(pSet64Instance) :
         (isObject ? ENTRYPOINT_OFFSET(pSetObjInstance)
         : ENTRYPOINT_OFFSET(pSet32Instance));
-    callRuntimeHelperImmRegLocationRegLocation(cUnit, setterOffset,
-                                               fieldIdx, rlObj, rlSrc);
+    callRuntimeHelperImmRegLocationRegLocation(cUnit, setterOffset, fieldIdx, rlObj, rlSrc, true);
   }
 }
 
@@ -1089,9 +1135,8 @@
                                                    type_idx)) {
     // Call out to helper which resolves type and verifies access.
     // Resolved type returned in rRET0.
-    callRuntimeHelperImmReg(cUnit,
-                            ENTRYPOINT_OFFSET(pInitializeTypeAndVerifyAccessFromCode),
-                            type_idx, rlMethod.lowReg);
+    callRuntimeHelperImmReg(cUnit, ENTRYPOINT_OFFSET(pInitializeTypeAndVerifyAccessFromCode),
+                            type_idx, rlMethod.lowReg, true);
     RegLocation rlResult = oatGetReturn(cUnit, false);
     storeValue(cUnit, rlDest, rlResult);
   } else {
@@ -1119,8 +1164,8 @@
       // TUNING: move slow path to end & remove unconditional branch
       LIR* target1 = newLIR0(cUnit, kPseudoTargetLabel);
       // Call out to helper, which will return resolved type in rARG0
-      callRuntimeHelperImmReg(cUnit, ENTRYPOINT_OFFSET(pInitializeTypeFromCode),
-                              type_idx, rlMethod.lowReg);
+      callRuntimeHelperImmReg(cUnit, ENTRYPOINT_OFFSET(pInitializeTypeFromCode), type_idx,
+                              rlMethod.lowReg, true);
       RegLocation rlResult = oatGetReturn(cUnit, false);
       storeValue(cUnit, rlDest, rlResult);
       /*
@@ -1167,18 +1212,19 @@
       opIT(cUnit, kArmCondEq, "T");
     }
     opRegCopy(cUnit, rARG0, rARG2);   // .eq
-    opReg(cUnit, kOpBlx, rTgt);    // .eq, helper(Method*, string_idx)
+    LIR* callInst = opReg(cUnit, kOpBlx, rTgt);    // .eq, helper(Method*, string_idx)
+    markSafepointPC(cUnit, callInst);
     oatFreeTemp(cUnit, rTgt);
 #elif defined(TARGET_MIPS)
     LIR* branch = opCmpImmBranch(cUnit, kCondNe, rRET0, 0, NULL);
     opRegCopy(cUnit, rARG0, rARG2);   // .eq
-    opReg(cUnit, kOpBlx, rTgt);
+    LIR* callInst = opReg(cUnit, kOpBlx, rTgt);
+    markSafepointPC(cUnit, callInst);
     oatFreeTemp(cUnit, rTgt);
     LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
     branch->target = target;
 #else
-    callRuntimeHelperRegReg(cUnit, ENTRYPOINT_OFFSET(pResolveStringFromCode),
-                            rARG2, rARG1);
+    callRuntimeHelperRegReg(cUnit, ENTRYPOINT_OFFSET(pResolveStringFromCode), rARG2, rARG1, true);
 #endif
     genBarrier(cUnit);
     storeValue(cUnit, rlDest, oatGetReturn(cUnit, false));
@@ -1209,7 +1255,7 @@
   } else {
     funcOffset = ENTRYPOINT_OFFSET(pAllocObjectFromCodeWithAccessCheck);
   }
-  callRuntimeHelperImmMethod(cUnit, funcOffset, type_idx);
+  callRuntimeHelperImmMethod(cUnit, funcOffset, type_idx, true);
   RegLocation rlResult = oatGetReturn(cUnit, false);
   storeValue(cUnit, rlDest, rlResult);
 }
@@ -1217,8 +1263,7 @@
 void genThrow(CompilationUnit* cUnit, RegLocation rlSrc)
 {
   oatFlushAllRegs(cUnit);
-  callRuntimeHelperRegLocation(cUnit, ENTRYPOINT_OFFSET(pDeliverException),
-                               rlSrc);
+  callRuntimeHelperRegLocation(cUnit, ENTRYPOINT_OFFSET(pDeliverException), rlSrc, true);
 }
 
 void genInstanceof(CompilationUnit* cUnit, uint32_t type_idx, RegLocation rlDest,
@@ -1234,9 +1279,8 @@
                                                    type_idx)) {
     // Check we have access to type_idx and if not throw IllegalAccessError,
     // returns Class* in rARG0
-    callRuntimeHelperImm(cUnit,
-                         ENTRYPOINT_OFFSET(pInitializeTypeAndVerifyAccessFromCode),
-                         type_idx);
+    callRuntimeHelperImm(cUnit, ENTRYPOINT_OFFSET(pInitializeTypeAndVerifyAccessFromCode),
+                         type_idx, true);
     opRegCopy(cUnit, classReg, rRET0);  // Align usage with fast path
     loadValueDirectFixed(cUnit, rlSrc, rARG0);  // rARG0 <= ref
   } else {
@@ -1254,8 +1298,7 @@
       LIR* hopBranch = opCmpImmBranch(cUnit, kCondNe, classReg, 0, NULL);
       // Not resolved
       // Call out to helper, which will return resolved type in rRET0
-      callRuntimeHelperImm(cUnit, ENTRYPOINT_OFFSET(pInitializeTypeFromCode),
-                           type_idx);
+      callRuntimeHelperImm(cUnit, ENTRYPOINT_OFFSET(pInitializeTypeFromCode), type_idx, true);
       opRegCopy(cUnit, rARG2, rRET0); // Align usage with fast path
       loadValueDirectFixed(cUnit, rlSrc, rARG0);  /* reload Ref */
       // Rejoin code paths
@@ -1269,6 +1312,7 @@
   DCHECK_EQ(Object::ClassOffset().Int32Value(), 0);
   loadWordDisp(cUnit, rARG0,  Object::ClassOffset().Int32Value(), rARG1);
   /* rARG0 is ref, rARG1 is ref->klass_, rARG2 is class */
+  LIR* callInst;
 #if defined(TARGET_ARM)
   /* Uses conditional nullification */
   int rTgt = loadHelper(cUnit,
@@ -1277,7 +1321,7 @@
   opIT(cUnit, kArmCondEq, "EE");   // if-convert the test
   loadConstant(cUnit, rARG0, 1);     // .eq case - load true
   opRegCopy(cUnit, rARG0, rARG2);    // .ne case - arg0 <= class
-  opReg(cUnit, kOpBlx, rTgt);    // .ne case: helper(class, ref->class)
+  callInst = opReg(cUnit, kOpBlx, rTgt);    // .ne case: helper(class, ref->class)
   oatFreeTemp(cUnit, rTgt);
 #else
   /* Uses branchovers */
@@ -1287,14 +1331,14 @@
   int rTgt = loadHelper(cUnit,
                         ENTRYPOINT_OFFSET(pInstanceofNonTrivialFromCode));
   opRegCopy(cUnit, rARG0, rARG2);    // .ne case - arg0 <= class
-  opReg(cUnit, kOpBlx, rTgt);    // .ne case: helper(class, ref->class)
+  callInst = opReg(cUnit, kOpBlx, rTgt);    // .ne case: helper(class, ref->class)
   oatFreeTemp(cUnit, rTgt);
 #else
   opRegCopy(cUnit, rARG0, rARG2);
-  opThreadMem(cUnit, kOpBlx,
-              ENTRYPOINT_OFFSET(pInstanceofNonTrivialFromCode));
+  callInst = opThreadMem(cUnit, kOpBlx, ENTRYPOINT_OFFSET(pInstanceofNonTrivialFromCode));
 #endif
 #endif
+  markSafepointPC(cUnit, callInst);
   oatClobberCalleeSave(cUnit);
   /* branch targets here */
   LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
@@ -1319,9 +1363,8 @@
     // Check we have access to type_idx and if not throw IllegalAccessError,
     // returns Class* in rRET0
     // InitializeTypeAndVerifyAccess(idx, method)
-    callRuntimeHelperImmReg(cUnit,
-                            ENTRYPOINT_OFFSET(pInitializeTypeAndVerifyAccessFromCode),
-                            type_idx, rARG1);
+    callRuntimeHelperImmReg(cUnit, ENTRYPOINT_OFFSET(pInitializeTypeAndVerifyAccessFromCode),
+                            type_idx, rARG1, true);
     opRegCopy(cUnit, classReg, rRET0);  // Align usage with fast path
   } else {
     // Load dex cache entry into classReg (rARG2)
@@ -1338,9 +1381,8 @@
       // Not resolved
       // Call out to helper, which will return resolved type in rARG0
       // InitializeTypeFromCode(idx, method)
-      callRuntimeHelperImmReg(cUnit,
-                              ENTRYPOINT_OFFSET(pInitializeTypeFromCode),
-                              type_idx, rARG1);
+      callRuntimeHelperImmReg(cUnit, ENTRYPOINT_OFFSET(pInitializeTypeFromCode), type_idx, rARG1,
+                              true);
       opRegCopy(cUnit, classReg, rARG0); // Align usage with fast path
       // Rejoin code paths
       LIR* hopTarget = newLIR0(cUnit, kPseudoTargetLabel);
@@ -1357,8 +1399,7 @@
   /* rARG1 now contains object->klass_ */
 #if defined(TARGET_MIPS) || defined(TARGET_X86)
   LIR* branch2 = opCmpBranch(cUnit, kCondEq, rARG1, classReg, NULL);
-  callRuntimeHelperRegReg(cUnit, ENTRYPOINT_OFFSET(pCheckCastFromCode),
-                          rARG1, rARG2);
+  callRuntimeHelperRegReg(cUnit, ENTRYPOINT_OFFSET(pCheckCastFromCode), rARG1, rARG2, true);
 #else  // defined(TARGET_ARM)
   int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pCheckCastFromCode));
   opRegReg(cUnit, kOpCmp, rARG1, classReg);
@@ -1366,7 +1407,8 @@
   opRegCopy(cUnit, rARG0, rARG1);
   opRegCopy(cUnit, rARG1, rARG2);
   oatClobberCalleeSave(cUnit);
-  opReg(cUnit, kOpBlx, rTgt);
+  LIR* callInst = opReg(cUnit, kOpBlx, rTgt);
+  markSafepointPC(cUnit, callInst);
   oatFreeTemp(cUnit, rTgt);
 #endif
   /* branch target here */
@@ -1404,8 +1446,8 @@
 
   // Get the array's class.
   loadWordDisp(cUnit, rArray, Object::ClassOffset().Int32Value(), rArrayClass);
-  callRuntimeHelperRegReg(cUnit, ENTRYPOINT_OFFSET(pCanPutArrayElementFromCode),
-                          rValue, rArrayClass);
+  callRuntimeHelperRegReg(cUnit, ENTRYPOINT_OFFSET(pCanPutArrayElementFromCode), rValue,
+                          rArrayClass, true);
   // Redo loadValues in case they didn't survive the call.
   loadValueDirectFixed(cUnit, rlArray, rArray);  // Reload array
   loadValueDirectFixed(cUnit, rlIndex, rIndex);  // Reload index
@@ -1717,7 +1759,7 @@
       return true;
   }
   oatFlushAllRegs(cUnit);   /* Send everything to home location */
-  callRuntimeHelperRegLocationRegLocation(cUnit, funcOffset, rlSrc1, rlShift);
+  callRuntimeHelperRegLocationRegLocation(cUnit, funcOffset, rlSrc1, rlShift, false);
   RegLocation rlResult = oatGetReturnWide(cUnit, false);
   storeValueWide(cUnit, rlDest, rlResult);
   return false;
@@ -1843,6 +1885,7 @@
     if (checkZero) {
       genImmedCheck(cUnit, kCondEq, rARG1, 0, kThrowDivZero);
     }
+    // NOTE: callout here is not a safepoint
 #if !defined(TARGET_X86)
     opReg(cUnit, kOpBlx, rTgt);
     oatFreeTemp(cUnit, rTgt);
@@ -2101,7 +2144,7 @@
       } else {
         isDiv = false;
       }
-      callRuntimeHelperRegImm(cUnit, funcOffset, rARG0, lit);
+      callRuntimeHelperRegImm(cUnit, funcOffset, rARG0, lit, false);
       if (isDiv)
         rlResult = oatGetReturn(cUnit, false);
       else
@@ -2249,6 +2292,7 @@
       genImmedCheck(cUnit, kCondEq, tReg, 0, kThrowDivZero);
       oatFreeTemp(cUnit, tReg);
       loadValueDirectWideFixed(cUnit, rlSrc1, rARG0, rARG1);
+      // NOTE: callout here is not a safepoint
 #if !defined(TARGET_X86)
       opReg(cUnit, kOpBlx, rTgt);
       oatFreeTemp(cUnit, rTgt);
@@ -2257,7 +2301,7 @@
 #endif
     } else {
       callRuntimeHelperRegLocationRegLocation(cUnit, funcOffset,
-                          rlSrc1, rlSrc2);
+                          rlSrc1, rlSrc2, false);
     }
     // Adjust return regs in to handle case of rem returning rARG2/rARG3
     if (retReg == rRET0)
@@ -2282,7 +2326,7 @@
   } else {
     loadValueDirectFixed(cUnit, rlSrc, rARG0);
   }
-  callRuntimeHelperRegLocation(cUnit, funcOffset, rlSrc);
+  callRuntimeHelperRegLocation(cUnit, funcOffset, rlSrc, false);
   if (rlDest.wide) {
     RegLocation rlResult;
     rlResult = oatGetReturnWide(cUnit, rlDest.fp);
@@ -2332,7 +2376,7 @@
       return true;
   }
   oatFlushAllRegs(cUnit);   /* Send everything to home location */
-  callRuntimeHelperRegLocationRegLocation(cUnit, funcOffset, rlSrc1, rlSrc2);
+  callRuntimeHelperRegLocationRegLocation(cUnit, funcOffset, rlSrc1, rlSrc2, false);
   rlResult = oatGetReturn(cUnit, true);
   storeValue(cUnit, rlDest, rlResult);
   return false;
@@ -2375,7 +2419,7 @@
       return true;
   }
   oatFlushAllRegs(cUnit);   /* Send everything to home location */
-  callRuntimeHelperRegLocationRegLocation(cUnit, funcOffset, rlSrc1, rlSrc2);
+  callRuntimeHelperRegLocationRegLocation(cUnit, funcOffset, rlSrc1, rlSrc2, false);
   rlResult = oatGetReturnWide(cUnit, true);
   storeValueWide(cUnit, rlDest, rlResult);
   return false;
@@ -2441,13 +2485,15 @@
   opRegImm(cUnit, kOpCmp, rSUSPEND, 0);
   opIT(cUnit, kArmCondNe, "T");
   loadConstant(cUnit, rARG2, offset);   // arg2 <- Entry code
-  opReg(cUnit, kOpBlx, rSUSPEND);
+  LIR* callInst = opReg(cUnit, kOpBlx, rSUSPEND);
+  markSafepointPC(cUnit, callInst);
 #elif defined(TARGET_X86)
   UNIMPLEMENTED(FATAL);
 #else
   LIR* branch = opCmpImmBranch(cUnit, kCondEq, rSUSPEND, 0, NULL);
   loadConstant(cUnit, rARG2, offset);
-  opReg(cUnit, kOpBlx, rSUSPEND);
+  LIR* callInst = opReg(cUnit, kOpBlx, rSUSPEND);
+  markSafepointPC(cUnit, callInst);
   LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
   branch->target = (LIR*)target;
 #endif
@@ -2467,7 +2513,8 @@
     UNIMPLEMENTED(FATAL);
 #else
     int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pTestSuspendFromCode));
-    opReg(cUnit, kOpBlx, rTgt);
+    LIR* callInst = opReg(cUnit, kOpBlx, rTgt);
+    markSafepointPC(cUnit, callInst);
     // Refresh rSUSPEND
     loadWordDisp(cUnit, rSELF,
            ENTRYPOINT_OFFSET(pUpdateDebuggerFromCode),
diff --git a/src/compiler/codegen/GenInvoke.cc b/src/compiler/codegen/GenInvoke.cc
index 7190a8b..1bfcf0e 100644
--- a/src/compiler/codegen/GenInvoke.cc
+++ b/src/compiler/codegen/GenInvoke.cc
@@ -540,14 +540,14 @@
   opRegRegImm(cUnit, kOpAdd, rARG0, rSP, outsOffset);
   opRegRegImm(cUnit, kOpAdd, rARG1, rSP, startOffset);
   callRuntimeHelperRegRegImm(cUnit, ENTRYPOINT_OFFSET(pMemcpy),
-                             rARG0, rARG1, (info->numArgWords - 3) * 4);
+                             rARG0, rARG1, (info->numArgWords - 3) * 4, false);
 #else
   if (info->numArgWords >= 20) {
     // Generate memcpy
     opRegRegImm(cUnit, kOpAdd, rARG0, rSP, outsOffset);
     opRegRegImm(cUnit, kOpAdd, rARG1, rSP, startOffset);
     callRuntimeHelperRegRegImm(cUnit, ENTRYPOINT_OFFSET(pMemcpy),
-                               rARG0, rARG1, (info->numArgWords - 3) * 4);
+                               rARG0, rARG1, (info->numArgWords - 3) * 4, false);
   } else {
     // Use vldm/vstm pair using rARG3 as a temp
     int regsLeft = std::min(info->numArgWords - 3, 16);
@@ -858,6 +858,7 @@
   oatInsertGrowableList(cUnit, &cUnit->intrinsicLaunchpads,
               (intptr_t)launchPad);
   opCmpImmBranch(cUnit, kCondGt, regChar, 0xFFFF, launchPad);
+  // NOTE: not a safepoint
 #if !defined(TARGET_X86)
   opReg(cUnit, kOpBlx, rTgt);
 #else
@@ -898,6 +899,7 @@
   oatInsertGrowableList(cUnit, &cUnit->intrinsicLaunchpads,
                         (intptr_t)launchPad);
   opCmpImmBranch(cUnit, kCondEq, regCmp, 0, launchPad);
+  // NOTE: not a safepoint
 #if !defined(TARGET_X86)
   opReg(cUnit, kOpBlx, rTgt);
 #else
diff --git a/src/compiler/codegen/LocalOptimizations.cc b/src/compiler/codegen/LocalOptimizations.cc
index 2fc7ae0..1dca491 100644
--- a/src/compiler/codegen/LocalOptimizations.cc
+++ b/src/compiler/codegen/LocalOptimizations.cc
@@ -406,17 +406,20 @@
           if (slot < LD_LATENCY) break;
         }
 
+        // Don't look across a barrier label
+        if ((prevLIR->opcode == kPseudoTargetLabel) ||
+            (prevLIR->opcode == kPseudoSafepointPC) ||
+            (prevLIR->opcode == kPseudoBarrier)) {
+          break;
+        }
+
         /*
-         * NOTE: now prevLIR is guaranteed to be a non-pseudo
-         * instruction (ie accessing EncodingMap[prevLIR->opcode] is
-         * safe).
-         *
          * Try to find two instructions with load/use dependency until
          * the remaining instructions are less than LD_LATENCY.
          */
-        if (((curLIR->useMask & prevLIR->defMask) &&
-           (EncodingMap[prevLIR->opcode].flags & IS_LOAD)) ||
-           (slot < LD_LATENCY)) {
+        bool prevIsLoad = isPseudoOpcode(prevLIR->opcode) ? false :
+            (EncodingMap[prevLIR->opcode].flags & IS_LOAD);
+        if (((curLIR->useMask & prevLIR->defMask) && prevIsLoad) || (slot < LD_LATENCY)) {
           break;
         }
       }
diff --git a/src/compiler/codegen/MethodBitcode.cc b/src/compiler/codegen/MethodBitcode.cc
index 8d62750..c4e1b9d 100644
--- a/src/compiler/codegen/MethodBitcode.cc
+++ b/src/compiler/codegen/MethodBitcode.cc
@@ -29,7 +29,9 @@
 #include <llvm/Support/Casting.h>
 #include <llvm/Support/InstIterator.h>
 
-static const char* kLabelFormat = "L0x%x_%d";
+static const char* kLabelFormat = "%c0x%x_%d";
+static const char kNormalBlock = 'L';
+static const char kCatchBlock = 'C';
 
 namespace art {
 extern const RegLocation badLoc;
@@ -1975,8 +1977,8 @@
     bool entryBlock = (bb->blockType == kEntryBlock);
     llvm::BasicBlock* llvmBB =
         llvm::BasicBlock::Create(*cUnit->context, entryBlock ? "entry" :
-                                 StringPrintf(kLabelFormat, offset, bb->id),
-                                 cUnit->func);
+                                 StringPrintf(kLabelFormat, bb->catchEntry ? kCatchBlock :
+                                              kNormalBlock, offset, bb->id), cUnit->func);
     if (entryBlock) {
         cUnit->entryBB = llvmBB;
         cUnit->placeholderBB =
@@ -2857,17 +2859,27 @@
   bool isEntry = (bb == &cUnit->func->getEntryBlock());
   // Define the starting label
   LIR* blockLabel = cUnit->blockToLabelMap.Get(bb);
-  // Extract the starting offset from the block's name
+  // Extract the type and starting offset from the block's name
+  char blockType = kNormalBlock;
   if (!isEntry) {
     const char* blockName = bb->getName().str().c_str();
     int dummy;
-    sscanf(blockName, kLabelFormat, &blockLabel->operands[0], &dummy);
+    sscanf(blockName, kLabelFormat, &blockType, &blockLabel->operands[0], &dummy);
+    cUnit->currentDalvikOffset = blockLabel->operands[0];
+  } else {
+    cUnit->currentDalvikOffset = 0;
   }
   // Set the label kind
   blockLabel->opcode = kPseudoNormalBlockLabel;
   // Insert the label
   oatAppendLIR(cUnit, blockLabel);
 
+  LIR* headLIR = NULL;
+
+  if (blockType == kCatchBlock) {
+    headLIR = newLIR0(cUnit, kPseudoSafepointPC);
+  }
+
   // Free temp registers and reset redundant store tracking */
   oatResetRegPool(cUnit);
   oatResetDefTracking(cUnit);
@@ -2875,10 +2887,7 @@
   //TODO: restore oat incoming liveness optimization
   oatClobberAllRegs(cUnit);
 
-  LIR* headLIR = NULL;
-
   if (isEntry) {
-    cUnit->currentDalvikOffset = 0;
     RegLocation* argLocs = (RegLocation*)
         oatNew(cUnit, sizeof(RegLocation) * cUnit->numIns, true, kAllocMisc);
     llvm::Function::arg_iterator it(cUnit->func->arg_begin());
diff --git a/src/compiler/codegen/MethodCodegenDriver.cc b/src/compiler/codegen/MethodCodegenDriver.cc
index 606a1ed..7d612b0 100644
--- a/src/compiler/codegen/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/MethodCodegenDriver.cc
@@ -124,11 +124,12 @@
   if (DISPLAY_MISSING_TARGETS) {
     genShowTarget(cUnit);
   }
+  LIR* callInst;
 #if !defined(TARGET_X86)
-  opReg(cUnit, kOpBlx, rINVOKE_TGT);
+  callInst = opReg(cUnit, kOpBlx, rINVOKE_TGT);
 #else
   if (fastPath && info->type != kInterface) {
-    opMem(cUnit, kOpBlx, rARG0, Method::GetCodeOffset().Int32Value());
+    callInst = opMem(cUnit, kOpBlx, rARG0, Method::GetCodeOffset().Int32Value());
   } else {
     int trampoline = 0;
     switch (info->type) {
@@ -151,9 +152,10 @@
     default:
       LOG(FATAL) << "Unexpected invoke type";
     }
-    opThreadMem(cUnit, kOpBlx, trampoline);
+    callInst = opThreadMem(cUnit, kOpBlx, trampoline);
   }
 #endif
+  markSafepointPC(cUnit, callInst);
 
   oatClobberCalleeSave(cUnit);
   if (info->result.location != kLocInvalid) {
@@ -867,6 +869,7 @@
 bool methodBlockCodeGen(CompilationUnit* cUnit, BasicBlock* bb)
 {
   if (bb->blockType == kDead) return false;
+  cUnit->currentDalvikOffset = bb->startOffset;
   MIR* mir;
   LIR* labelList = cUnit->blockLabelList;
   int blockId = bb->id;
@@ -878,13 +881,19 @@
   labelList[blockId].opcode = kPseudoNormalBlockLabel;
   oatAppendLIR(cUnit, (LIR*) &labelList[blockId]);
 
+  LIR* headLIR = NULL;
+
+  /* If this is a catch block, mark the beginning as a safepoint */
+  if (bb->catchEntry) {
+    headLIR = newLIR0(cUnit, kPseudoSafepointPC);
+  }
+
   /* Free temp registers and reset redundant store tracking */
   oatResetRegPool(cUnit);
   oatResetDefTracking(cUnit);
 
   oatClobberAllRegs(cUnit);
 
-  LIR* headLIR = NULL;
 
   if (bb->blockType == kEntryBlock) {
     int startVReg = cUnit->numDalvikRegisters - cUnit->numIns;
diff --git a/src/compiler/codegen/arm/ArmLIR.h b/src/compiler/codegen/arm/ArmLIR.h
index 4004fbb..36a11f2 100644
--- a/src/compiler/codegen/arm/ArmLIR.h
+++ b/src/compiler/codegen/arm/ArmLIR.h
@@ -291,6 +291,7 @@
  * Assemble.cc.
  */
 enum ArmOpcode {
+  kPseudoSafepointPC = -17,
   kPseudoIntrinsicRetry = -16,
   kPseudoSuspendTarget = -15,
   kPseudoThrowTarget = -14,
diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc
index 925bbf2..3584a52 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -492,7 +492,8 @@
   // Materialize a pointer to the fill data image
   newLIR3(cUnit, kThumb2Adr, r1, 0, (intptr_t)tabRec);
   oatClobberCalleeSave(cUnit);
-  opReg(cUnit, kOpBlx, rLR);
+  LIR* callInst = opReg(cUnit, kOpBlx, rLR);
+  markSafepointPC(cUnit, callInst);
 }
 
 void genNegFloat(CompilationUnit* cUnit, RegLocation rlDest, RegLocation rlSrc)
@@ -564,7 +565,8 @@
   // Go expensive route - artLockObjectFromCode(self, obj);
   loadWordDisp(cUnit, rSELF, ENTRYPOINT_OFFSET(pLockObjectFromCode), rLR);
   oatClobberCalleeSave(cUnit);
-  opReg(cUnit, kOpBlx, rLR);
+  LIR* callInst = opReg(cUnit, kOpBlx, rLR);
+  markSafepointPC(cUnit, callInst);
   oatGenMemBarrier(cUnit, kSY);
 }
 
@@ -595,7 +597,8 @@
   // Go expensive route - UnlockObjectFromCode(obj);
   loadWordDisp(cUnit, rSELF, ENTRYPOINT_OFFSET(pUnlockObjectFromCode), rLR);
   oatClobberCalleeSave(cUnit);
-  opReg(cUnit, kOpBlx, rLR);
+  LIR* callInst = opReg(cUnit, kOpBlx, rLR);
+  markSafepointPC(cUnit, callInst);
   oatGenMemBarrier(cUnit, kSY);
 }
 
diff --git a/src/compiler/codegen/mips/FP/MipsFP.cc b/src/compiler/codegen/mips/FP/MipsFP.cc
index 2bf26e4..f121a54 100644
--- a/src/compiler/codegen/mips/FP/MipsFP.cc
+++ b/src/compiler/codegen/mips/FP/MipsFP.cc
@@ -204,6 +204,7 @@
     loadValueDirectFixed(cUnit, rlSrc2, rARG1);
   }
   int rTgt = loadHelper(cUnit, offset);
+  // NOTE: not a safepoint
   opReg(cUnit, kOpBlx, rTgt);
   RegLocation rlResult = oatGetReturn(cUnit, false);
   storeValue(cUnit, rlDest, rlResult);
diff --git a/src/compiler/codegen/mips/Mips32/Gen.cc b/src/compiler/codegen/mips/Mips32/Gen.cc
index c304836..b0cad0f 100644
--- a/src/compiler/codegen/mips/Mips32/Gen.cc
+++ b/src/compiler/codegen/mips/Mips32/Gen.cc
@@ -261,7 +261,8 @@
 
   // And go...
   oatClobberCalleeSave(cUnit);
-  opReg(cUnit, kOpBlx, rTgt); // ( array*, fill_data* )
+  LIR* callInst = opReg(cUnit, kOpBlx, rTgt); // ( array*, fill_data* )
+  markSafepointPC(cUnit, callInst);
 }
 
 void genNegFloat(CompilationUnit *cUnit, RegLocation rlDest, RegLocation rlSrc)
@@ -295,7 +296,8 @@
   // Go expensive route - artLockObjectFromCode(self, obj);
   int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pLockObjectFromCode));
   oatClobberCalleeSave(cUnit);
-  opReg(cUnit, kOpBlx, rTgt);
+  LIR* callInst = opReg(cUnit, kOpBlx, rTgt);
+  markSafepointPC(cUnit, callInst);
 }
 
 /*
@@ -310,7 +312,8 @@
   // Go expensive route - UnlockObjectFromCode(obj);
   int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pUnlockObjectFromCode));
   oatClobberCalleeSave(cUnit);
-  opReg(cUnit, kOpBlx, rTgt);
+  LIR* callInst = opReg(cUnit, kOpBlx, rTgt);
+  markSafepointPC(cUnit, callInst);
 }
 
 /*
diff --git a/src/compiler/codegen/mips/MipsLIR.h b/src/compiler/codegen/mips/MipsLIR.h
index 5852b31..c78cd8d 100644
--- a/src/compiler/codegen/mips/MipsLIR.h
+++ b/src/compiler/codegen/mips/MipsLIR.h
@@ -333,6 +333,7 @@
  * Assemble.cc.
  */
 enum MipsOpCode {
+  kPseudoSafepointPC = -17,
   kPseudoIntrinsicRetry = -16,
   kPseudoSuspendTarget = -15,
   kPseudoThrowTarget = -14,
diff --git a/src/compiler/codegen/x86/X86/Gen.cc b/src/compiler/codegen/x86/X86/Gen.cc
index 4bfc531..fb8bcd7 100644
--- a/src/compiler/codegen/x86/X86/Gen.cc
+++ b/src/compiler/codegen/x86/X86/Gen.cc
@@ -141,7 +141,7 @@
 }
 
 void callRuntimeHelperRegReg(CompilationUnit* cUnit, int helperOffset,
-                             int arg0, int arg1);
+                             int arg0, int arg1, bool safepointPC);
 /*
  * Array data table format:
  *  ushort ident = 0x0300   magic value
@@ -174,9 +174,8 @@
   newLIR1(cUnit, kX86StartOfMethod, rARG2);
   newLIR2(cUnit, kX86PcRelAdr, rARG1, (intptr_t)tabRec);
   newLIR2(cUnit, kX86Add32RR, rARG1, rARG2);
-  callRuntimeHelperRegReg(cUnit,
-                          ENTRYPOINT_OFFSET(pHandleFillArrayDataFromCode),
-                          rARG0, rARG1);
+  callRuntimeHelperRegReg(cUnit, ENTRYPOINT_OFFSET(pHandleFillArrayDataFromCode), rARG0, rARG1,
+                          true);
 }
 
 void genNegFloat(CompilationUnit *cUnit, RegLocation rlDest, RegLocation rlSrc)
@@ -199,7 +198,7 @@
 }
 
 LIR* genNullCheck(CompilationUnit* cUnit, int sReg, int mReg, int optFlags);
-void callRuntimeHelperReg(CompilationUnit* cUnit, int helperOffset, int arg0);
+void callRuntimeHelperReg(CompilationUnit* cUnit, int helperOffset, int arg0, bool safepointPC);
 
 void genMonitorEnter(CompilationUnit* cUnit, int optFlags, RegLocation rlSrc)
 {
@@ -215,7 +214,7 @@
   newLIR3(cUnit, kX86LockCmpxchgMR, rCX, Object::MonitorOffset().Int32Value(), rDX);
   LIR* branch = newLIR2(cUnit, kX86Jcc8, 0, kX86CondEq);
   // If lock is held, go the expensive route - artLockObjectFromCode(self, obj);
-  callRuntimeHelperReg(cUnit, ENTRYPOINT_OFFSET(pLockObjectFromCode), rCX);
+  callRuntimeHelperReg(cUnit, ENTRYPOINT_OFFSET(pLockObjectFromCode), rCX, true);
   branch->target = newLIR0(cUnit, kPseudoTargetLabel);
 }
 
@@ -236,7 +235,7 @@
   LIR* branch2 = newLIR1(cUnit, kX86Jmp8, 0);
   branch->target = newLIR0(cUnit, kPseudoTargetLabel);
   // Otherwise, go the expensive route - UnlockObjectFromCode(obj);
-  callRuntimeHelperReg(cUnit, ENTRYPOINT_OFFSET(pUnlockObjectFromCode), rAX);
+  callRuntimeHelperReg(cUnit, ENTRYPOINT_OFFSET(pUnlockObjectFromCode), rAX, true);
   branch2->target = newLIR0(cUnit, kPseudoTargetLabel);
 }
 
diff --git a/src/compiler/codegen/x86/X86LIR.h b/src/compiler/codegen/x86/X86LIR.h
index 7a9d90d..9872313 100644
--- a/src/compiler/codegen/x86/X86LIR.h
+++ b/src/compiler/codegen/x86/X86LIR.h
@@ -297,6 +297,7 @@
  * Assemble.cc.
  */
 enum X86OpCode {
+  kPseudoSafepointPC = -17,
   kPseudoIntrinsicRetry = -16,
   kPseudoSuspendTarget = -15,
   kPseudoThrowTarget = -14,
diff --git a/src/exception_test.cc b/src/exception_test.cc
index 37788df..bd792f7 100644
--- a/src/exception_test.cc
+++ b/src/exception_test.cc
@@ -136,8 +136,7 @@
   fake_stack.push_back(reinterpret_cast<uintptr_t>(method_g_));
   fake_stack.push_back(0);
   fake_stack.push_back(0);
-  // We add 2 to the native pc since the stack walker always subtracts two from a return pc.
-  fake_stack.push_back(method_f_->ToNativePC(dex_pc) + 2);  // return pc
+  fake_stack.push_back(method_f_->ToNativePC(dex_pc));  // return pc
 
   // Create/push fake 16byte stack frame for method f
   fake_stack.push_back(reinterpret_cast<uintptr_t>(method_f_));
@@ -154,7 +153,7 @@
   fake_stack.push_back(0);
 
   // Set up thread to appear as if we called out of method_g_ at pc dex 3
-  thread->SetTopOfStack(&fake_stack[0], method_g_->ToNativePC(dex_pc) + 2);  // return pc
+  thread->SetTopOfStack(&fake_stack[0], method_g_->ToNativePC(dex_pc));  // return pc
 #else
   // Create/push fake 20-byte shadow frame for method g
   fake_stack.push_back(0);
diff --git a/src/oat/runtime/support_stubs.cc b/src/oat/runtime/support_stubs.cc
index 41de9f7..138f722 100644
--- a/src/oat/runtime/support_stubs.cc
+++ b/src/oat/runtime/support_stubs.cc
@@ -97,8 +97,7 @@
 #endif
   if (type == Runtime::kUnknownMethod) {
     DCHECK(called->IsRuntimeMethod());
-    // less two as return address may span into next dex instruction
-    uint32_t dex_pc = caller->ToDexPC(caller_pc - 2);
+    uint32_t dex_pc = caller->ToDexPC(caller_pc);
     const DexFile::CodeItem* code = MethodHelper(caller).GetCodeItem();
     CHECK_LT(dex_pc, code->insns_size_in_code_units_);
     const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
diff --git a/src/oatdump.cc b/src/oatdump.cc
index e0ee148..86137d5 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -446,6 +446,17 @@
     const uint8_t* native_pc = reinterpret_cast<const uint8_t*>(code);
     const uint8_t* end_native_pc = native_pc + code_size;
 
+    /*
+     * TODO: the mapping table is no longer useful for identifying Dalvik opcodes.  This was
+     * a nice feature, so we ought to come up with another mechanism (at least when debugging).
+     * Keeping the old Dalvik disassembly code for reference.
+     */
+    disassembler_->Dump(os, native_pc, end_native_pc);
+    (void)raw_mapping_table;
+    (void)dex_file;
+    (void)code_item;
+
+#if 0
     if (raw_mapping_table == NULL) {
       // code but no mapping table is most likely caused by code created by the JNI compiler
       disassembler_->Dump(os, native_pc, end_native_pc);
@@ -470,6 +481,7 @@
       CHECK(cur_pc < cur_pc_end);
       disassembler_->Dump(os, cur_pc, cur_pc_end);
     }
+#endif
   }
 
   const std::string host_prefix_;
diff --git a/src/object.cc b/src/object.cc
index fc89841..b131517 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -480,22 +480,14 @@
   }
   size_t mapping_table_length = GetMappingTableLength();
   uint32_t sought_offset = pc - reinterpret_cast<uintptr_t>(GetOatCode(this));
-  uint32_t best_offset = 0;
-  uint32_t best_dex_offset = 0;
   for (size_t i = 0; i < mapping_table_length; i += 2) {
-    uint32_t map_offset = mapping_table[i];
-    uint32_t map_dex_offset = mapping_table[i + 1];
-    if (map_offset == sought_offset) {
-      best_offset = map_offset;
-      best_dex_offset = map_dex_offset;
-      break;
-    }
-    if (map_offset < sought_offset && map_offset > best_offset) {
-      best_offset = map_offset;
-      best_dex_offset = map_dex_offset;
+    if (mapping_table[i] == sought_offset) {
+      return mapping_table[i + 1];
     }
   }
-  return best_dex_offset;
+  LOG(FATAL) << "Failed to find Dex offset for PC offset 0x" << std::hex << sought_offset
+             << " in " << PrettyMethod(this);
+  return DexFile::kDexNoIndex;
 #else
   // Compiler LLVM doesn't use the machine pc, we just use dex pc instead.
   return static_cast<uint32_t>(pc);
diff --git a/src/object.h b/src/object.h
index e746f73..03aadda 100644
--- a/src/object.h
+++ b/src/object.h
@@ -682,7 +682,12 @@
     if (code == 0) {
       return pc == 0;
     }
-    return (code <= pc && pc < code + GetCodeSize());
+    /*
+     * During a stack walk, a return PC may point to the end of the code + 1
+     * (in the case that the last instruction is a call that isn't expected to
+     * return.  Thus, we check <= code + GetCodeSize().
+     */
+    return (code <= pc && pc <= code + GetCodeSize());
   }
 
   void AssertPcIsWithinCode(uintptr_t pc) const
diff --git a/src/stack.cc b/src/stack.cc
index 9795a77..2b2530b 100644
--- a/src/stack.cc
+++ b/src/stack.cc
@@ -68,7 +68,7 @@
   if (cur_shadow_frame_ != NULL) {
     return cur_shadow_frame_->GetDexPC();
   } else if (cur_quick_frame_ != NULL) {
-    return GetMethod()->ToDexPC(AdjustQuickFramePcForDexPcComputation(cur_quick_frame_pc_));
+    return GetMethod()->ToDexPC(cur_quick_frame_pc_);
   } else {
     return 0;
   }
@@ -176,7 +176,7 @@
   CHECK(method->GetClass() == Method::GetMethodClass() ||
         method->GetClass() == Method::GetConstructorClass());
   if (cur_quick_frame_ != NULL) {
-    method->AssertPcIsWithinCode(AdjustQuickFramePcForDexPcComputation(cur_quick_frame_pc_));
+    method->AssertPcIsWithinCode(cur_quick_frame_pc_);
     // Frame sanity.
     size_t frame_size = method->GetFrameSizeInBytes();
     CHECK_NE(frame_size, 0u);
diff --git a/src/stack.h b/src/stack.h
index 60218b1..91b0cf1 100644
--- a/src/stack.h
+++ b/src/stack.h
@@ -391,15 +391,6 @@
   Context* const context_;
 };
 
-static inline uintptr_t AdjustQuickFramePcForDexPcComputation(uintptr_t pc) {
-  // Quick methods record a mapping from quick PCs to Dex PCs at the beginning of the code for
-  // each dex instruction. When walking the stack, the return PC will be set to the instruction
-  // following call which will likely be the start of the next dex instruction. Adjust the PC
-  // for these cases by 2 bytes in case the return PC also has the thumb bit set.
-  if (pc > 0) { pc -= 2; }
-  return pc;
-}
-
 }  // namespace art
 
 #endif  // ART_SRC_STACK_H_
diff --git a/src/thread.cc b/src/thread.cc
index 57f9905..13b9fb7 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -1551,7 +1551,7 @@
       } else {
         // Unwind stack when an exception occurs during method tracing
         if (UNLIKELY(method_tracing_active_ && IsTraceExitPc(GetCurrentQuickFramePc()))) {
-          uintptr_t pc = AdjustQuickFramePcForDexPcComputation(TraceMethodUnwindFromCode(Thread::Current()));
+          uintptr_t pc = TraceMethodUnwindFromCode(Thread::Current());
           dex_pc = method->ToDexPC(pc);
         } else {
           dex_pc = GetDexPc();