am 3d661949: Real fix for 064

* commit '3d661949dba4a2f3311e6f74a3c42b5addf1f534':
  Real fix for 064
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 6ab849a..e26677d 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -1357,11 +1357,11 @@
     size_t end = declaring_class->NumVirtualMethods();
     bool found = false;
     for (size_t i = 0; i < end; i++) {
-      oat_method_index++;
       if (declaring_class->GetVirtualMethod(i) == method) {
         found = true;
         break;
       }
+      oat_method_index++;
     }
     CHECK(found) << "Didn't find oat method index for virtual method: " << PrettyMethod(method);
   }
diff --git a/src/compiled_method.cc b/src/compiled_method.cc
index f718991..bf88880 100644
--- a/src/compiled_method.cc
+++ b/src/compiled_method.cc
@@ -35,9 +35,7 @@
     : instruction_set_(instruction_set), frame_size_in_bytes_(frame_size_in_bytes),
       core_spill_mask_(core_spill_mask), fp_spill_mask_(fp_spill_mask) {
   CHECK_NE(code.size(), 0U);
-  if (instruction_set != kX86) {
-    CHECK_GE(vmap_table.size(), 1U);  // should always contain an entry for LR
-  }
+  CHECK_GE(vmap_table.size(), 1U);  // should always contain an entry for LR
   DCHECK_EQ(vmap_table.size(),
             static_cast<uint32_t>(__builtin_popcount(core_spill_mask)
                                   + __builtin_popcount(fp_spill_mask)));
diff --git a/src/compiler.cc b/src/compiler.cc
index fe4f4fc..f64b1cb 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -677,7 +677,7 @@
           referrer_class->CanAccessMember(methods_class,
                                           resolved_method->GetAccessFlags())) {
         vtable_idx = resolved_method->GetMethodIndex();
-        const bool kEnableSharpening = false;
+        const bool kEnableSharpening = true;
         if (kEnableSharpening && type == kVirtual &&
             (resolved_method->IsFinal() || methods_class->IsFinal())) {
           stats_->ResolvedMethod(kVirtual);
diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc
index 8ffcc72..fc7fcb4 100644
--- a/src/compiler/Frontend.cc
+++ b/src/compiler/Frontend.cc
@@ -785,7 +785,6 @@
         cUnit->enableDebug = compilerDebugFlags;
         cUnit->printMe = VLOG_IS_ON(compiler) || (cUnit->enableDebug & (1 << kDebugVerbose));
     }
-
     /* Are we generating code for the debugger? */
     if (compiler.IsDebuggingSupported()) {
         cUnit->genDebugger = true;
@@ -1008,10 +1007,8 @@
     for (size_t i = 0 ; i < cUnit->coreVmapTable.size(); i++) {
         vmapTable.push_back(cUnit->coreVmapTable[i]);
     }
-    if (cUnit->instructionSet != kX86) {
-        // Add a marker to take place of lr
-        vmapTable.push_back(INVALID_VREG);
-    }
+    // Add a marker to take place of lr
+    vmapTable.push_back(INVALID_VREG);
     // Combine vmap tables - core regs, then fp regs
     for (uint32_t i = 0; i < cUnit->fpVmapTable.size(); i++) {
         vmapTable.push_back(cUnit->fpVmapTable[i]);
diff --git a/src/compiler/codegen/GenCommon.cc b/src/compiler/codegen/GenCommon.cc
index 72a596a..aee5b50 100644
--- a/src/compiler/codegen/GenCommon.cc
+++ b/src/compiler/codegen/GenCommon.cc
@@ -248,7 +248,7 @@
     loadConstant(cUnit, rARG0, type_idx);            // arg0 <- type_id
     loadValueDirectFixed(cUnit, rlSrc, rARG2);       // arg2 <- count
     callRuntimeHelper(cUnit, rTgt);
-    RegLocation rlResult = oatGetReturn(cUnit);
+    RegLocation rlResult = oatGetReturn(cUnit, false);
     storeValue(cUnit, rlDest, rlResult);
 }
 
@@ -567,10 +567,10 @@
         loadConstant(cUnit, rARG0, fieldIdx);
         callRuntimeHelper(cUnit, rTgt);
         if (isLongOrDouble) {
-            RegLocation rlResult = oatGetReturnWide(cUnit);
+            RegLocation rlResult = oatGetReturnWide(cUnit, rlDest.fp);
             storeValueWide(cUnit, rlDest, rlResult);
         } else {
-            RegLocation rlResult = oatGetReturn(cUnit);
+            RegLocation rlResult = oatGetReturn(cUnit, rlDest.fp);
             storeValue(cUnit, rlDest, rlResult);
         }
     }
@@ -761,10 +761,10 @@
         loadConstant(cUnit, rARG0, fieldIdx);
         callRuntimeHelper(cUnit, rTgt);
         if (isLongOrDouble) {
-            RegLocation rlResult = oatGetReturnWide(cUnit);
+            RegLocation rlResult = oatGetReturnWide(cUnit, rlDest.fp);
             storeValueWide(cUnit, rlDest, rlResult);
         } else {
-            RegLocation rlResult = oatGetReturn(cUnit);
+            RegLocation rlResult = oatGetReturn(cUnit, rlDest.fp);
             storeValue(cUnit, rlDest, rlResult);
         }
     }
@@ -851,7 +851,7 @@
         opRegCopy(cUnit, rARG1, rlMethod.lowReg);
         loadConstant(cUnit, rARG0, type_idx);
         callRuntimeHelper(cUnit, rTgt);
-        RegLocation rlResult = oatGetReturn(cUnit);
+        RegLocation rlResult = oatGetReturn(cUnit, false);
         storeValue(cUnit, rlDest, rlResult);
     } else {
         // We're don't need access checks, load type from dex cache
@@ -884,7 +884,7 @@
             opRegCopy(cUnit, rARG1, rlMethod.lowReg);
             loadConstant(cUnit, rARG0, type_idx);
             callRuntimeHelper(cUnit, rTgt);
-            RegLocation rlResult = oatGetReturn(cUnit);
+            RegLocation rlResult = oatGetReturn(cUnit, false);
             storeValue(cUnit, rlDest, rlResult);
             /*
              * Because we have stores of the target value on two paths,
@@ -938,7 +938,7 @@
         branch->target = target;
 #endif
         genBarrier(cUnit);
-        storeValue(cUnit, rlDest, oatGetReturn(cUnit));
+        storeValue(cUnit, rlDest, oatGetReturn(cUnit, false));
     } else {
         RegLocation rlMethod = loadCurrMethod(cUnit);
         int resReg = oatAllocTemp(cUnit);
@@ -971,7 +971,7 @@
     loadCurrMethodDirect(cUnit, rARG1);    // arg1 <= Method*
     loadConstant(cUnit, rARG0, type_idx);  // arg0 <- type_idx
     callRuntimeHelper(cUnit, rTgt);
-    RegLocation rlResult = oatGetReturn(cUnit);
+    RegLocation rlResult = oatGetReturn(cUnit, false);
     storeValue(cUnit, rlDest, rlResult);
 }
 
@@ -1050,7 +1050,7 @@
     oatClobberCalleeSave(cUnit);
     /* branch targets here */
     LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
-    RegLocation rlResult = oatGetReturn(cUnit);
+    RegLocation rlResult = oatGetReturn(cUnit, false);
     storeValue(cUnit, rlDest, rlResult);
     branch1->target = target;
 #if !defined(TARGET_ARM)
@@ -1434,7 +1434,7 @@
     loadValueDirectWideFixed(cUnit, rlSrc1, rARG0, rARG1);
     loadValueDirect(cUnit, rlShift, rARG2);
     callRuntimeHelper(cUnit, rTgt);
-    RegLocation rlResult = oatGetReturnWide(cUnit);
+    RegLocation rlResult = oatGetReturnWide(cUnit, false);
     storeValueWide(cUnit, rlDest, rlResult);
     return false;
 }
@@ -1559,7 +1559,7 @@
         }
         callRuntimeHelper(cUnit, rTgt);
         if (retReg == rRET0)
-            rlResult = oatGetReturn(cUnit);
+            rlResult = oatGetReturn(cUnit, false);
         else
             rlResult = oatGetReturnAlt(cUnit);
         storeValue(cUnit, rlDest, rlResult);
@@ -1807,7 +1807,7 @@
             loadConstant(cUnit, rARG1, lit);
             callRuntimeHelper(cUnit, rTgt);
             if (isDiv)
-                rlResult = oatGetReturn(cUnit);
+                rlResult = oatGetReturn(cUnit, false);
             else
                 rlResult = oatGetReturnAlt(cUnit);
             storeValue(cUnit, rlDest, rlResult);
@@ -1957,7 +1957,7 @@
         callRuntimeHelper(cUnit, rTgt);
         // Adjust return regs in to handle case of rem returning rARG2/rARG3
         if (retReg == rRET0)
-            rlResult = oatGetReturnWide(cUnit);
+            rlResult = oatGetReturnWide(cUnit, false);
         else
             rlResult = oatGetReturnWideAlt(cUnit);
         storeValueWide(cUnit, rlDest, rlResult);
@@ -1987,12 +1987,12 @@
     if (tgtSize == 1) {
         RegLocation rlResult;
         rlDest = oatGetDest(cUnit, mir, 0);
-        rlResult = oatGetReturn(cUnit);
+        rlResult = oatGetReturn(cUnit, rlDest.fp);
         storeValue(cUnit, rlDest, rlResult);
     } else {
         RegLocation rlResult;
         rlDest = oatGetDestWide(cUnit, mir, 0, 1);
-        rlResult = oatGetReturnWide(cUnit);
+        rlResult = oatGetReturnWide(cUnit, rlDest.fp);
         storeValueWide(cUnit, rlDest, rlResult);
     }
     return false;
@@ -2039,7 +2039,7 @@
     loadValueDirectFixed(cUnit, rlSrc1, rARG0);
     loadValueDirectFixed(cUnit, rlSrc2, rARG1);
     callRuntimeHelper(cUnit, rTgt);
-    rlResult = oatGetReturn(cUnit);
+    rlResult = oatGetReturn(cUnit, true);
     storeValue(cUnit, rlDest, rlResult);
     return false;
 }
@@ -2089,7 +2089,7 @@
     loadValueDirectWideFixed(cUnit, rlSrc2, rARG2, rARG3);
 #endif
     callRuntimeHelper(cUnit, rTgt);
-    rlResult = oatGetReturnWide(cUnit);
+    rlResult = oatGetReturnWide(cUnit, true);
     storeValueWide(cUnit, rlDest, rlResult);
     return false;
 }
diff --git a/src/compiler/codegen/MethodCodegenDriver.cc b/src/compiler/codegen/MethodCodegenDriver.cc
index 6aa6366..eff4199 100644
--- a/src/compiler/codegen/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/MethodCodegenDriver.cc
@@ -25,9 +25,11 @@
                             INVALID_REG, INVALID_REG, INVALID_SREG};
 
 /* Mark register usage state and return long retloc */
-RegLocation oatGetReturnWide(CompilationUnit* cUnit)
+RegLocation oatGetReturnWide(CompilationUnit* cUnit, bool isDouble)
 {
-    RegLocation res = LOC_C_RETURN_WIDE;
+    RegLocation gpr_res = LOC_C_RETURN_WIDE;
+    RegLocation fpr_res = LOC_C_RETURN_WIDE_DOUBLE;
+    RegLocation res = isDouble ? fpr_res : gpr_res;
     oatClobber(cUnit, res.lowReg);
     oatClobber(cUnit, res.highReg);
     oatLockTemp(cUnit, res.lowReg);
@@ -36,9 +38,11 @@
     return res;
 }
 
-RegLocation oatGetReturn(CompilationUnit* cUnit)
+RegLocation oatGetReturn(CompilationUnit* cUnit, bool isFloat)
 {
-    RegLocation res = LOC_C_RETURN;
+  RegLocation gpr_res = LOC_C_RETURN;
+  RegLocation fpr_res = LOC_C_RETURN_FLOAT;
+  RegLocation res = isFloat ? fpr_res : gpr_res;
     oatClobber(cUnit, res.lowReg);
     if (cUnit->instructionSet == kMips) {
         oatMarkInUse(cUnit, res.lowReg);
@@ -195,27 +199,29 @@
             if (!cUnit->attrs & METHOD_IS_LEAF) {
                 genSuspendTest(cUnit, mir);
             }
-            storeValue(cUnit, oatGetReturn(cUnit), rlSrc[0]);
+            storeValue(cUnit, oatGetReturn(cUnit, cUnit->shorty[0] == 'F'),
+                       rlSrc[0]);
             break;
 
         case Instruction::RETURN_WIDE:
             if (!cUnit->attrs & METHOD_IS_LEAF) {
                 genSuspendTest(cUnit, mir);
             }
-            storeValueWide(cUnit, oatGetReturnWide(cUnit), rlSrc[0]);
+            storeValueWide(cUnit, oatGetReturnWide(cUnit,
+                                           cUnit->shorty[0] == 'D'), rlSrc[0]);
             break;
 
         case Instruction::MOVE_RESULT_WIDE:
             if (mir->optimizationFlags & MIR_INLINED)
                 break;  // Nop - combined w/ previous invoke
-            storeValueWide(cUnit, rlDest, oatGetReturnWide(cUnit));
+            storeValueWide(cUnit, rlDest, oatGetReturnWide(cUnit, rlDest.fp));
             break;
 
         case Instruction::MOVE_RESULT:
         case Instruction::MOVE_RESULT_OBJECT:
             if (mir->optimizationFlags & MIR_INLINED)
                 break;  // Nop - combined w/ previous invoke
-            storeValue(cUnit, rlDest, oatGetReturn(cUnit));
+            storeValue(cUnit, rlDest, oatGetReturn(cUnit, rlDest.fp));
             break;
 
         case Instruction::MOVE:
diff --git a/src/compiler/codegen/Ralloc.h b/src/compiler/codegen/Ralloc.h
index d32545c..aa5439a 100644
--- a/src/compiler/codegen/Ralloc.h
+++ b/src/compiler/codegen/Ralloc.h
@@ -124,7 +124,7 @@
 // Get the LocRecord associated with an SSA name def.
 extern RegLocation oatGetDest(CompilationUnit* cUnit, MIR* mir, int num);
 
-extern RegLocation oatGetReturnWide(CompilationUnit* cUnit);
+extern RegLocation oatGetReturnWide(CompilationUnit* cUnit, bool isDouble);
 
 /* Clobber all regs that might be used by an external C call */
 extern void oatClobberCalleeSave(CompilationUnit* cUnit);
@@ -161,7 +161,7 @@
 
 extern RegLocation oatGetReturnWideAlt(CompilationUnit* cUnit);
 
-extern RegLocation oatGetReturn(CompilationUnit* cUnit);
+extern RegLocation oatGetReturn(CompilationUnit* cUnit, bool isFloat);
 
 extern RegLocation oatGetReturnAlt(CompilationUnit* cUnit);
 
diff --git a/src/compiler/codegen/arm/ArmLIR.h b/src/compiler/codegen/arm/ArmLIR.h
index e3370df..a43702c 100644
--- a/src/compiler/codegen/arm/ArmLIR.h
+++ b/src/compiler/codegen/arm/ArmLIR.h
@@ -128,6 +128,8 @@
 #define LOC_C_RETURN {kLocPhysReg, 0, 0, 0, 0, 0, 1, r0, INVALID_REG,\
                       INVALID_SREG}
 #define LOC_C_RETURN_WIDE {kLocPhysReg, 1, 0, 0, 0, 0, 1, r0, r1, INVALID_SREG}
+#define LOC_C_RETURN_FLOAT  LOC_C_RETURN
+#define LOC_C_RETURN_WIDE_DOUBLE  LOC_C_RETURN_WIDE
 
 enum ResourceEncodingPos {
     kGPReg0     = 0,
diff --git a/src/compiler/codegen/mips/FP/MipsFP.cc b/src/compiler/codegen/mips/FP/MipsFP.cc
index 3bbb3d7..d8ca0a1 100644
--- a/src/compiler/codegen/mips/FP/MipsFP.cc
+++ b/src/compiler/codegen/mips/FP/MipsFP.cc
@@ -218,7 +218,7 @@
     }
     int rTgt = loadHelper(cUnit, offset);
     opReg(cUnit, kOpBlx, rTgt);
-    RegLocation rlResult = oatGetReturn(cUnit);
+    RegLocation rlResult = oatGetReturn(cUnit, false);
     storeValue(cUnit, rlDest, rlResult);
     return false;
 }
diff --git a/src/compiler/codegen/mips/MipsLIR.h b/src/compiler/codegen/mips/MipsLIR.h
index 8fdfe59..5c8fc34 100644
--- a/src/compiler/codegen/mips/MipsLIR.h
+++ b/src/compiler/codegen/mips/MipsLIR.h
@@ -147,10 +147,12 @@
 /* RegisterLocation templates return values (r_V0, or r_V0/r_V1) */
 #define LOC_C_RETURN {kLocPhysReg, 0, 0, 0, 0, 0, 1, r_V0, INVALID_REG, \
                       INVALID_SREG}
+#define LOC_C_RETURN_FLOAT  LOC_C_RETURN
 #define LOC_C_RETURN_ALT {kLocPhysReg, 0, 0, 0, 0, 0, 1, r_F0, INVALID_REG, \
-                      INVALID_SREG}
+                          INVALID_SREG}
 #define LOC_C_RETURN_WIDE {kLocPhysReg, 1, 0, 0, 0, 0, 1, r_RESULT0, r_RESULT1,\
                            INVALID_SREG}
+#define LOC_C_RETURN_WIDE_DOUBLE  LOC_C_RETURN_WIDE
 #define LOC_C_RETURN_WIDE_ALT {kLocPhysReg, 1, 0, 0, 0, 0, 1, r_FRESULT0,\
                                r_FRESULT1, INVALID_SREG}
 
diff --git a/src/compiler/codegen/x86/ArchFactory.cc b/src/compiler/codegen/x86/ArchFactory.cc
index 2d15318..f2c9c71 100644
--- a/src/compiler/codegen/x86/ArchFactory.cc
+++ b/src/compiler/codegen/x86/ArchFactory.cc
@@ -27,54 +27,36 @@
 bool genAddLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
                 RegLocation rlSrc1, RegLocation rlSrc2)
 {
-    UNIMPLEMENTED(WARNING) << "genAddLong";
-#if 0
     rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg);
     rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
     RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
     /*
      *  [v1 v0] =  [a1 a0] + [a3 a2];
-     *    addu v0,a2,a0
-     *    addu t1,a3,a1
-     *    sltu v1,v0,a2
-     *    addu v1,v1,t1
+     *    add v0,a2,a0
+     *    adc v1,a3,a1
      */
 
     opRegRegReg(cUnit, kOpAdd, rlResult.lowReg, rlSrc2.lowReg, rlSrc1.lowReg);
-    int tReg = oatAllocTemp(cUnit);
-    opRegRegReg(cUnit, kOpAdd, tReg, rlSrc2.highReg, rlSrc1.highReg);
-    newLIR3(cUnit, kX86Sltu, rlResult.highReg, rlResult.lowReg, rlSrc2.lowReg);
-    opRegRegReg(cUnit, kOpAdd, rlResult.highReg, rlResult.highReg, tReg);
-    oatFreeTemp(cUnit, tReg);
+    opRegRegReg(cUnit, kOpAdc, rlResult.highReg, rlSrc2.highReg, rlSrc1.highReg);
     storeValueWide(cUnit, rlDest, rlResult);
-#endif
     return false;
 }
 
 bool genSubLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
                 RegLocation rlSrc1, RegLocation rlSrc2)
 {
-    UNIMPLEMENTED(WARNING) << "genSubLong";
-#if 0
     rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg);
     rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
     RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
     /*
      *  [v1 v0] =  [a1 a0] - [a3 a2];
-     *    subu    v0,a0,a2
-     *    subu    v1,a1,a3
-     *    sltu    t1,a0,v0
-     *    subu    v1,v1,t1
+     *    sub    v0,a0,a2
+     *    sbb    v1,a1,a3
      */
 
     opRegRegReg(cUnit, kOpSub, rlResult.lowReg, rlSrc1.lowReg, rlSrc2.lowReg);
-    opRegRegReg(cUnit, kOpSub, rlResult.highReg, rlSrc1.highReg, rlSrc2.highReg);
-    int tReg = oatAllocTemp(cUnit);
-    newLIR3(cUnit, kX86Sltu, tReg, rlSrc1.lowReg, rlResult.lowReg);
-    opRegRegReg(cUnit, kOpSub, rlResult.highReg, rlResult.highReg, tReg);
-    oatFreeTemp(cUnit, tReg);
+    opRegRegReg(cUnit, kOpSbc, rlResult.highReg, rlSrc1.highReg, rlSrc2.highReg);
     storeValueWide(cUnit, rlDest, rlResult);
-#endif
     return false;
 }
 
@@ -123,34 +105,34 @@
 #endif
 }
 
-void spillCoreRegs(CompilationUnit* cUnit)
-{
-    if (cUnit->numCoreSpills == 0) {
-        return;
+void spillCoreRegs(CompilationUnit* cUnit) {
+  if (cUnit->numCoreSpills == 0) {
+    return;
+  }
+  // Spill mask not including fake return address register
+  uint32_t mask = cUnit->coreSpillMask & ~(1 << rRET);
+  int offset = cUnit->frameSize - 4;
+  for (int reg = 0; mask; mask >>= 1, reg++) {
+    if (mask & 0x1) {
+      offset -= 4;
+      storeWordDisp(cUnit, rSP, offset, reg);
     }
-    uint32_t mask = cUnit->coreSpillMask;
-    int offset = cUnit->frameSize - 4;
-    for (int reg = 0; mask; mask >>= 1, reg++) {
-        if (mask & 0x1) {
-            offset -= 4;
-            storeWordDisp(cUnit, rSP, offset, reg);
-        }
-    }
+  }
 }
 
-void unSpillCoreRegs(CompilationUnit* cUnit)
-{
-    if (cUnit->numCoreSpills == 0) {
-        return;
+void unSpillCoreRegs(CompilationUnit* cUnit) {
+  if (cUnit->numCoreSpills == 0) {
+    return;
+  }
+  // Spill mask not including fake return address register
+  uint32_t mask = cUnit->coreSpillMask & ~(1 << rRET);
+  int offset = cUnit->frameSize - 4;
+  for (int reg = 0; mask; mask >>= 1, reg++) {
+    if (mask & 0x1) {
+      offset -= 4;
+      loadWordDisp(cUnit, rSP, offset, reg);
     }
-    uint32_t mask = cUnit->coreSpillMask;
-    int offset = cUnit->frameSize - 4;
-    for (int reg = 0; mask; mask >>= 1, reg++) {
-        if (mask & 0x1) {
-            offset -= 4;
-            loadWordDisp(cUnit, rSP, offset, reg);
-        }
-    }
+  }
 }
 
 void opRegThreadMem(CompilationUnit* cUnit, OpKind op, int rDest, int threadOffset) {
@@ -280,19 +262,17 @@
 
 
 /* Common initialization routine for an architecture family */
-bool oatArchInit()
-{
-    int i;
+bool oatArchInit() {
+  int i;
 
-    for (i = 0; i < kX86Last; i++) {
-        if (EncodingMap[i].opcode != i) {
-            LOG(FATAL) << "Encoding order for " << EncodingMap[i].name <<
-               " is wrong: expecting " << i << ", seeing " <<
-               (int)EncodingMap[i].opcode;
-        }
+  for (i = 0; i < kX86Last; i++) {
+    if (EncodingMap[i].opcode != i) {
+      LOG(FATAL) << "Encoding order for " << EncodingMap[i].name
+          << " is wrong: expecting " << i << ", seeing " << (int)EncodingMap[i].opcode;
     }
+  }
 
-    return oatArchVariantInit();
+  return oatArchVariantInit();
 }
 
 }  // namespace art
diff --git a/src/compiler/codegen/x86/Assemble.cc b/src/compiler/codegen/x86/Assemble.cc
index cb06776..3d2b0e5 100644
--- a/src/compiler/codegen/x86/Assemble.cc
+++ b/src/compiler/codegen/x86/Assemble.cc
@@ -468,6 +468,9 @@
     DCHECK_EQ(0, entry->skeleton.extra_opcode1);
     DCHECK_EQ(0, entry->skeleton.extra_opcode2);
   }
+  if (FPREG(reg)) {
+    reg = reg & FP_REG_MASK;
+  }
   DCHECK_LT(reg, 8);
   uint8_t modrm = (3 << 6) | (entry->skeleton.modrm_opcode << 3) | reg;
   cUnit->codeBuffer.push_back(modrm);
@@ -518,6 +521,9 @@
     DCHECK_EQ(0, entry->skeleton.extra_opcode1);
     DCHECK_EQ(0, entry->skeleton.extra_opcode2);
   }
+  if (FPREG(reg)) {
+    reg = reg & FP_REG_MASK;
+  }
   DCHECK_LT(reg, 8);
   DCHECK_LT(base, 8);
   uint8_t modrm = (modrmForDisp(disp) << 6) | (reg << 3) | base;
@@ -560,6 +566,9 @@
     DCHECK_EQ(0, entry->skeleton.extra_opcode1);
     DCHECK_EQ(0, entry->skeleton.extra_opcode2);
   }
+  if (FPREG(reg)) {
+    reg = reg & FP_REG_MASK;
+  }
   DCHECK_LT(reg, 8);
   uint8_t modrm = (modrmForDisp(disp) << 6) | (reg << 3) | rSP;
   cUnit->codeBuffer.push_back(modrm);
@@ -596,6 +605,14 @@
     DCHECK_EQ(0, entry->skeleton.extra_opcode1);
     DCHECK_EQ(0, entry->skeleton.extra_opcode2);
   }
+  if (FPREG(reg1)) {
+    reg1 = reg1 & FP_REG_MASK;
+  }
+  if (FPREG(reg2)) {
+    reg2 = reg2 & FP_REG_MASK;
+  }
+  DCHECK_LT(reg1, 8);
+  DCHECK_LT(reg2, 8);
   uint8_t modrm = (3 << 6) | (reg1 << 3) | reg2;
   cUnit->codeBuffer.push_back(modrm);
   DCHECK_EQ(0, entry->skeleton.modrm_opcode);
diff --git a/src/compiler/codegen/x86/X86/Factory.cc b/src/compiler/codegen/x86/X86/Factory.cc
index c28bae9..f3fc84a 100644
--- a/src/compiler/codegen/x86/X86/Factory.cc
+++ b/src/compiler/codegen/x86/X86/Factory.cc
@@ -76,7 +76,7 @@
         }
     }
     DCHECK((EncodingMap[opcode].flags & IS_BINARY_OP) != 0);
-    LIR* res = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, rSrc, rDest);
+    LIR* res = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, rDest, rSrc);
     if (rDest == rSrc) {
         res->flags.isNop = true;
     }
@@ -502,7 +502,7 @@
           rDest = rDest - FP_DOUBLE;
         } else {
           DCHECK(FPREG(rDestHi));
-          DCHECK(rDest == (rDestHi - 1));
+          DCHECK_EQ(rDest, (rDestHi - 1));
         }
         rDestHi = rDest + 1;
       } else {
@@ -549,7 +549,7 @@
     if (rBase == rSP) {
       annotateDalvikRegAccess(load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
                               true /* isLoad */, is64bit);
-      if (is64bit) {
+      if (pair) {
         annotateDalvikRegAccess(load2, (displacement + HIWORD_OFFSET) >> 2,
                                 true /* isLoad */, is64bit);
       }
diff --git a/src/compiler/codegen/x86/X86/Gen.cc b/src/compiler/codegen/x86/X86/Gen.cc
index f3b8aa0..e7f18ca 100644
--- a/src/compiler/codegen/x86/X86/Gen.cc
+++ b/src/compiler/codegen/x86/X86/Gen.cc
@@ -437,51 +437,39 @@
 LIR* opRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
 {
     LIR *res = opRegCopyNoInsert(cUnit, rDest, rSrc);
-    oatAppendLIR(cUnit, (LIR*)res);
+    oatAppendLIR(cUnit, res);
     return res;
 }
 
 void opRegCopyWide(CompilationUnit *cUnit, int destLo, int destHi,
-                    int srcLo, int srcHi)
-{
-    UNIMPLEMENTED(WARNING) << "opRegCopyWide";
-#if 0
-    bool destFP = FPREG(destLo) && FPREG(destHi);
-    bool srcFP = FPREG(srcLo) && FPREG(srcHi);
-    assert(FPREG(srcLo) == FPREG(srcHi));
-    assert(FPREG(destLo) == FPREG(destHi));
-    if (destFP) {
-        if (srcFP) {
-            opRegCopy(cUnit, S2D(destLo, destHi), S2D(srcLo, srcHi));
-        } else {
-           /* note the operands are swapped for the mtc1 instr */
-            newLIR2(cUnit, kX86Mtc1, srcLo, destLo);
-            newLIR2(cUnit, kX86Mtc1, srcHi, destHi);
-        }
+                   int srcLo, int srcHi) {
+  bool destFP = FPREG(destLo) && FPREG(destHi);
+  bool srcFP = FPREG(srcLo) && FPREG(srcHi);
+  assert(FPREG(srcLo) == FPREG(srcHi));
+  assert(FPREG(destLo) == FPREG(destHi));
+  LOG(INFO) << "RegCopyWide: destLo=" << destLo << " destHi=" << destHi
+      << " srcLo=" << srcLo << " srcHi=" << srcHi
+      << " dFP=" << destFP << " sFP=" << srcFP;
+  if (destFP) {
+    if (srcFP) {
+      opRegCopy(cUnit, S2D(destLo, destHi), S2D(srcLo, srcHi));
     } else {
-        if (srcFP) {
-            newLIR2(cUnit, kX86Mfc1, destLo, srcLo);
-            newLIR2(cUnit, kX86Mfc1, destHi, srcHi);
-        } else {
-            // Handle overlap
-            if (srcHi == destLo) {
-                opRegCopy(cUnit, destHi, srcHi);
-                opRegCopy(cUnit, destLo, srcLo);
-            } else {
-                opRegCopy(cUnit, destLo, srcLo);
-                opRegCopy(cUnit, destHi, srcHi);
-            }
-        }
+      UNIMPLEMENTED(WARNING);
     }
-    // Handle overlap
-    if (srcHi == destLo) {
+  } else {
+    if (srcFP) {
+      UNIMPLEMENTED(WARNING);
+    } else {
+      // Handle overlap
+      if (srcHi == destLo) {
         opRegCopy(cUnit, destHi, srcHi);
         opRegCopy(cUnit, destLo, srcLo);
-    } else {
+      } else {
         opRegCopy(cUnit, destLo, srcLo);
         opRegCopy(cUnit, destHi, srcHi);
+      }
     }
-#endif
+  }
 }
 
 }  // namespace art
diff --git a/src/compiler/codegen/x86/X86/Ralloc.cc b/src/compiler/codegen/x86/X86/Ralloc.cc
index c7985e5..38b9df8 100644
--- a/src/compiler/codegen/x86/X86/Ralloc.cc
+++ b/src/compiler/codegen/x86/X86/Ralloc.cc
@@ -29,97 +29,88 @@
  * high reg in next byte.
  */
 int oatAllocTypedTempPair(CompilationUnit *cUnit, bool fpHint,
-                                  int regClass)
-{
-    UNIMPLEMENTED(WARNING) << "oatAllocTypedTemp";
-    return 0;
-#if 0
-    int highReg;
-    int lowReg;
-    int res = 0;
+                          int regClass) {
+  int highReg;
+  int lowReg;
+  int res = 0;
 
-    if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg)) {
-        lowReg = oatAllocTempDouble(cUnit);
-        highReg = lowReg + 1;
-        res = (lowReg & 0xff) | ((highReg & 0xff) << 8);
-        return res;
-    }
-
-    lowReg = oatAllocTemp(cUnit);
-    highReg = oatAllocTemp(cUnit);
+  if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg)) {
+    lowReg = oatAllocTempDouble(cUnit);
+    highReg = lowReg + 1;
     res = (lowReg & 0xff) | ((highReg & 0xff) << 8);
     return res;
-#endif
+  }
+
+  lowReg = oatAllocTemp(cUnit);
+  highReg = oatAllocTemp(cUnit);
+  res = (lowReg & 0xff) | ((highReg & 0xff) << 8);
+  return res;
 }
 
-int oatAllocTypedTemp(CompilationUnit *cUnit, bool fpHint, int regClass)
-{
-    if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg))
-{
-        return oatAllocTempFloat(cUnit);
-}
-    return oatAllocTemp(cUnit);
+int oatAllocTypedTemp(CompilationUnit *cUnit, bool fpHint, int regClass) {
+  if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg)) {
+    return oatAllocTempFloat(cUnit);
+  }
+  return oatAllocTemp(cUnit);
 }
 
-void oatInitializeRegAlloc(CompilationUnit* cUnit)
-{
-    int numRegs = sizeof(coreRegs)/sizeof(*coreRegs);
-    int numReserved = sizeof(reservedRegs)/sizeof(*reservedRegs);
-    int numTemps = sizeof(coreTemps)/sizeof(*coreTemps);
-    int numFPRegs = sizeof(fpRegs)/sizeof(*fpRegs);
-    int numFPTemps = sizeof(fpTemps)/sizeof(*fpTemps);
-    RegisterPool *pool = (RegisterPool *)oatNew(cUnit, sizeof(*pool), true,
-                                                kAllocRegAlloc);
-    cUnit->regPool = pool;
-    pool->numCoreRegs = numRegs;
-    pool->coreRegs = (RegisterInfo *)
-            oatNew(cUnit, numRegs * sizeof(*cUnit->regPool->coreRegs),
-                   true, kAllocRegAlloc);
-    pool->numFPRegs = numFPRegs;
-    pool->FPRegs = (RegisterInfo *)
-            oatNew(cUnit, numFPRegs * sizeof(*cUnit->regPool->FPRegs), true,
-                   kAllocRegAlloc);
-    oatInitPool(pool->coreRegs, coreRegs, pool->numCoreRegs);
-    oatInitPool(pool->FPRegs, fpRegs, pool->numFPRegs);
-    // Keep special registers from being allocated
-    for (int i = 0; i < numReserved; i++) {
-        oatMarkInUse(cUnit, reservedRegs[i]);
-    }
-    // Mark temp regs - all others not in use can be used for promotion
-    for (int i = 0; i < numTemps; i++) {
-        oatMarkTemp(cUnit, coreTemps[i]);
-    }
-    for (int i = 0; i < numFPTemps; i++) {
-        oatMarkTemp(cUnit, fpTemps[i]);
-    }
-    // Construct the alias map.
-    cUnit->phiAliasMap = (int*)oatNew(cUnit, cUnit->numSSARegs *
-                                      sizeof(cUnit->phiAliasMap[0]), false,
-                                      kAllocDFInfo);
-    for (int i = 0; i < cUnit->numSSARegs; i++) {
-        cUnit->phiAliasMap[i] = i;
-    }
-    for (MIR* phi = cUnit->phiList; phi; phi = phi->meta.phiNext) {
-        int defReg = phi->ssaRep->defs[0];
-        for (int i = 0; i < phi->ssaRep->numUses; i++) {
-           for (int j = 0; j < cUnit->numSSARegs; j++) {
-               if (cUnit->phiAliasMap[j] == phi->ssaRep->uses[i]) {
-                   cUnit->phiAliasMap[j] = defReg;
-               }
-           }
+void oatInitializeRegAlloc(CompilationUnit* cUnit) {
+  int numRegs = sizeof(coreRegs)/sizeof(*coreRegs);
+  int numReserved = sizeof(reservedRegs)/sizeof(*reservedRegs);
+  int numTemps = sizeof(coreTemps)/sizeof(*coreTemps);
+  int numFPRegs = sizeof(fpRegs)/sizeof(*fpRegs);
+  int numFPTemps = sizeof(fpTemps)/sizeof(*fpTemps);
+  RegisterPool *pool = (RegisterPool *)oatNew(cUnit, sizeof(*pool), true,
+                                              kAllocRegAlloc);
+  cUnit->regPool = pool;
+  pool->numCoreRegs = numRegs;
+  pool->coreRegs = (RegisterInfo *)
+                oatNew(cUnit, numRegs * sizeof(*cUnit->regPool->coreRegs),
+                       true, kAllocRegAlloc);
+  pool->numFPRegs = numFPRegs;
+  pool->FPRegs = (RegisterInfo *)
+                oatNew(cUnit, numFPRegs * sizeof(*cUnit->regPool->FPRegs), true,
+                       kAllocRegAlloc);
+  oatInitPool(pool->coreRegs, coreRegs, pool->numCoreRegs);
+  oatInitPool(pool->FPRegs, fpRegs, pool->numFPRegs);
+  // Keep special registers from being allocated
+  for (int i = 0; i < numReserved; i++) {
+    oatMarkInUse(cUnit, reservedRegs[i]);
+  }
+  // Mark temp regs - all others not in use can be used for promotion
+  for (int i = 0; i < numTemps; i++) {
+    oatMarkTemp(cUnit, coreTemps[i]);
+  }
+  for (int i = 0; i < numFPTemps; i++) {
+    oatMarkTemp(cUnit, fpTemps[i]);
+  }
+  // Construct the alias map.
+  cUnit->phiAliasMap = (int*)oatNew(cUnit, cUnit->numSSARegs *
+                                    sizeof(cUnit->phiAliasMap[0]), false,
+                                    kAllocDFInfo);
+  for (int i = 0; i < cUnit->numSSARegs; i++) {
+    cUnit->phiAliasMap[i] = i;
+  }
+  for (MIR* phi = cUnit->phiList; phi; phi = phi->meta.phiNext) {
+    int defReg = phi->ssaRep->defs[0];
+    for (int i = 0; i < phi->ssaRep->numUses; i++) {
+      for (int j = 0; j < cUnit->numSSARegs; j++) {
+        if (cUnit->phiAliasMap[j] == phi->ssaRep->uses[i]) {
+          cUnit->phiAliasMap[j] = defReg;
         }
+      }
     }
+  }
 }
 
 void freeRegLocTemps(CompilationUnit* cUnit, RegLocation rlKeep,
-                     RegLocation rlFree)
-{
-    if ((rlFree.lowReg != rlKeep.lowReg) && (rlFree.lowReg != rlKeep.highReg) &&
-        (rlFree.highReg != rlKeep.lowReg) && (rlFree.highReg != rlKeep.highReg)) {
-        // No overlap, free both
-        oatFreeTemp(cUnit, rlFree.lowReg);
-        oatFreeTemp(cUnit, rlFree.highReg);
-    }
+                     RegLocation rlFree) {
+  if ((rlFree.lowReg != rlKeep.lowReg) && (rlFree.lowReg != rlKeep.highReg) &&
+      (rlFree.highReg != rlKeep.lowReg) && (rlFree.highReg != rlKeep.highReg)) {
+    // No overlap, free both
+    oatFreeTemp(cUnit, rlFree.lowReg);
+    oatFreeTemp(cUnit, rlFree.highReg);
+  }
 }
 
 
diff --git a/src/compiler/codegen/x86/X86LIR.h b/src/compiler/codegen/x86/X86LIR.h
index 65f07cf..c805333 100644
--- a/src/compiler/codegen/x86/X86LIR.h
+++ b/src/compiler/codegen/x86/X86LIR.h
@@ -106,11 +106,11 @@
  */
 
 /* Offset to distingish FP regs */
-#define FP_REG_OFFSET 16
+#define FP_REG_OFFSET 32
 /* Offset to distinguish DP FP regs */
-#define FP_DOUBLE 32
+#define FP_DOUBLE (FP_REG_OFFSET + 16)
 /* Offset to distingish the extra regs */
-#define EXTRA_REG_OFFSET 64
+#define EXTRA_REG_OFFSET (FP_DOUBLE + 16)
 /* Reg types */
 #define REGTYPE(x) (x & (FP_REG_OFFSET | FP_DOUBLE))
 #define FPREG(x) ((x & FP_REG_OFFSET) == FP_REG_OFFSET)
@@ -128,15 +128,18 @@
  */
 #define S2D(x,y) ((x) | FP_DOUBLE)
 /* Mask to strip off fp flags */
-#define FP_REG_MASK (FP_REG_OFFSET-1)
+#define FP_REG_MASK 0xF
 /* non-existent Dalvik register */
 #define vNone   (-1)
 /* non-existant physical register */
 #define rNone   (-1)
 
-/* RegisterLocation templates return values (rAX, or rAX/rDX) */
-#define LOC_C_RETURN      {kLocPhysReg, 0, 0, 0, 0, 0, 1, rAX, INVALID_REG, INVALID_SREG}
-#define LOC_C_RETURN_WIDE {kLocPhysReg, 1, 0, 0, 0, 0, 1, rAX, rDX,         INVALID_SREG}
+/* RegisterLocation templates return values (rAX, rAX/rDX or XMM0) */
+//                               location,     wide, defined, fp, core, highWord, home, lowReg, highReg,     sRegLow
+#define LOC_C_RETURN             {kLocPhysReg, 0,    0,       0,  0,    0,        1,    rAX,    INVALID_REG, INVALID_SREG}
+#define LOC_C_RETURN_WIDE        {kLocPhysReg, 1,    0,       0,  0,    0,        1,    rAX,    rDX,         INVALID_SREG}
+#define LOC_C_RETURN_FLOAT       {kLocPhysReg, 0,    0,       1,  0,    0,        1,    fr0,    INVALID_REG, INVALID_SREG}
+#define LOC_C_RETURN_WIDE_DOUBLE {kLocPhysReg, 1,    0,       1,  0,    0,        1,    fr0,    fr1,         INVALID_SREG}
 
 enum ResourceEncodingPos {
     kGPReg0     = 0,
@@ -201,6 +204,7 @@
   r13    = 13,
   r14    = 14,
   r15    = 15,
+  rRET   = 16,  // fake return address register for core spill mask
   fr0  =  0 + FP_REG_OFFSET,
   fr1  =  1 + FP_REG_OFFSET,
   fr2  =  2 + FP_REG_OFFSET,
diff --git a/src/compiler/codegen/x86/X86RallocUtil.cc b/src/compiler/codegen/x86/X86RallocUtil.cc
index 1b4eca4..ff5391d 100644
--- a/src/compiler/codegen/x86/X86RallocUtil.cc
+++ b/src/compiler/codegen/x86/X86RallocUtil.cc
@@ -29,6 +29,8 @@
 
 void oatAdjustSpillMask(CompilationUnit* cUnit) {
   // Adjustment for LR spilling, x86 has no LR so nothing to do here
+  cUnit->coreSpillMask |= (1 << rRET);
+  cUnit->numCoreSpills++;
 }
 
 /*
@@ -138,17 +140,16 @@
 #endif
 }
 
-extern RegLocation oatGetReturnWideAlt(CompilationUnit* cUnit)
-{
-    RegLocation res = LOC_C_RETURN_WIDE;
-    res.lowReg = rAX;
-    res.highReg = rDX;
-    oatClobber(cUnit, rAX);
-    oatClobber(cUnit, rDX);
-    oatMarkInUse(cUnit, rAX);
-    oatMarkInUse(cUnit, rDX);
-    oatMarkPair(cUnit, res.lowReg, res.highReg);
-    return res;
+extern RegLocation oatGetReturnWideAlt(CompilationUnit* cUnit) {
+  RegLocation res = LOC_C_RETURN_WIDE;
+  CHECK(res.lowReg == rAX);
+  CHECK(res.highReg == rDX);
+  oatClobber(cUnit, rAX);
+  oatClobber(cUnit, rDX);
+  oatMarkInUse(cUnit, rAX);
+  oatMarkInUse(cUnit, rDX);
+  oatMarkPair(cUnit, res.lowReg, res.highReg);
+  return res;
 }
 
 extern RegLocation oatGetReturnAlt(CompilationUnit* cUnit)
diff --git a/src/dex_instruction_list.h b/src/dex_instruction_list.h
index 8a5b5ad..ed26795 100644
--- a/src/dex_instruction_list.h
+++ b/src/dex_instruction_list.h
@@ -53,7 +53,7 @@
   V(0x23, NEW_ARRAY, "new-array", k22c, true, kTypeRef, kContinue | kThrow, kVerifyRegA | kVerifyRegB | kVerifyRegCNewArray) \
   V(0x24, FILLED_NEW_ARRAY, "filled-new-array", k35c, false, kTypeRef, kContinue | kThrow, kVerifyRegBType | kVerifyVarArg) \
   V(0x25, FILLED_NEW_ARRAY_RANGE, "filled-new-array/range", k3rc, false, kTypeRef, kContinue | kThrow, kVerifyRegBType | kVerifyVarArgRange) \
-  V(0x26, FILL_ARRAY_DATA, "fill-array-data", k31t, false, kNone, kContinue, kVerifyRegA | kVerifyArrayData) \
+  V(0x26, FILL_ARRAY_DATA, "fill-array-data", k31t, false, kNone, kContinue | kThrow, kVerifyRegA | kVerifyArrayData) \
   V(0x27, THROW, "throw", k11x, false, kNone, kThrow, kVerifyRegA) \
   V(0x28, GOTO, "goto", k10t, false, kNone, kBranch, kVerifyBranchTarget) \
   V(0x29, GOTO_16, "goto/16", k20t, false, kNone, kBranch, kVerifyBranchTarget) \
diff --git a/src/jni_internal_test.cc b/src/jni_internal_test.cc
index 5c61afc..a67bec1 100644
--- a/src/jni_internal_test.cc
+++ b/src/jni_internal_test.cc
@@ -995,7 +995,6 @@
   EXPECT_EQ(INT_MIN, result.i);
 }
 
-#if defined(__arm__) || defined(ART_USE_LLVM_COMPILER)
 TEST_F(JniInternalTest, StaticIdentityDoubleMethod) {
   SirtRef<ClassLoader> class_loader(LoadDex("StaticLeafMethods"));
   CompileDirectMethod(class_loader.get(), "StaticLeafMethods", "identity", "(D)D");
@@ -1594,7 +1593,6 @@
   (*stub)(method, NULL, Thread::Current(), reinterpret_cast<byte*>(args), &result);
   EXPECT_EQ(3.0, result.d);
 }
-#endif  // __arm__ || ART_USE_LLVM_COMPILER
 
 TEST_F(JniInternalTest, Throw) {
   EXPECT_EQ(JNI_ERR, env_->Throw(NULL));
diff --git a/src/mem_map.cc b/src/mem_map.cc
index 92c6a59..885389d 100644
--- a/src/mem_map.cc
+++ b/src/mem_map.cc
@@ -29,7 +29,9 @@
 
 namespace art {
 
-size_t ParseHex(const std::string& string) {
+#if !defined(NDEBUG)
+
+static size_t ParseHex(const std::string& string) {
   CHECK_EQ(8U, string.size());
   const char* str = string.c_str();
   char* end;
@@ -39,17 +41,65 @@
   return value;
 }
 
+static void CheckMapRegion(uint32_t base, uint32_t limit, uint32_t start, uint32_t end, const std::string& maps) {
+  CHECK(!(base >= start && base < end)      // start of new within old
+        && !(limit > start && limit < end)  // end of new within old
+        && !(base <= start && limit > end)) // start/end of new includes all of old
+      << StringPrintf("Requested region %08x-%08x overlaps with existing map %08x-%08x\n",
+                      base, limit, start, end)
+      << maps;
+}
+
 void CheckMapRequest(byte* addr, size_t length) {
-#if !defined(NDEBUG)
-#if defined(__APPLE__)
-  UNIMPLEMENTED(WARNING);
-#else
   if (addr == NULL) {
     return;
   }
-  size_t base = reinterpret_cast<size_t>(addr);
-  size_t limit = base + length;
+  uint32_t base = reinterpret_cast<size_t>(addr);
+  uint32_t limit = base + length;
 
+#if defined(__APPLE__)
+  // Mac OS vmmap(1) output currently looks something like this:
+
+  // Virtual Memory Map of process 51036 (dex2oatd)
+  // Output report format:  2.2  -- 32-bit process
+  //
+  // ==== regions for process 51036  (non-writable and writable regions are interleaved)
+  // __PAGEZERO             00000000-00001000 [    4K     0K     0K] ---/--- SM=NUL          out/host/darwin-x86/bin/dex2oatd
+  // __TEXT                 00001000-00015000 [   80K    80K     0K] r-x/rwx SM=COW          out/host/darwin-x86/bin/dex2oatd
+  // __DATA                 00015000-00016000 [    4K     4K     4K] rw-/rwx SM=PRV          out/host/darwin-x86/bin/dex2oatd
+  // __LINKEDIT             00016000-00044000 [  184K   184K     0K] r--/rwx SM=COW          out/host/darwin-x86/bin/dex2oatd
+  // __TEXT                 00044000-00046000 [    8K     8K     4K] r-x/rwx SM=COW          out/host/darwin-x86/obj/lib/libnativehelper.dylib
+  // __DATA                 00046000-00047000 [    4K     4K     4K] rw-/rwx SM=ZER          out/host/darwin-x86/obj/lib/libnativehelper.dylib
+  // __LINKEDIT             00047000-0004a000 [   12K    12K     0K] r--/rwx SM=COW          out/host/darwin-x86/obj/lib/libnativehelper.dylib
+  // ...
+
+  std::string command(StringPrintf("vmmap -v -interleaved %d", getpid()));
+  FILE* fp = popen(command.c_str(), "r");
+  if (fp == NULL) {
+    PLOG(FATAL) << "popen failed";
+  }
+  std::vector<char> chars(512);
+  std::string maps;
+  while (fgets(&chars[0], chars.size(), fp) != NULL) {
+    std::string line(&chars[0]);
+    maps += line;
+    if (line.size() < 40 || line[31] != '-') {
+      continue;
+    }
+
+    std::string start_str(line.substr(22, 8));
+    std::string end_str(line.substr(31, 8));
+    uint32_t start = ParseHex(start_str);
+    uint32_t end = ParseHex(end_str);
+    CheckMapRegion(base, limit, start, end, maps);
+  }
+  if (ferror(fp)) {
+    PLOG(FATAL) << "fgets failed";
+  }
+  if (pclose(fp) == -1) {
+    PLOG(FATAL) << "pclose failed";
+  }
+#else // Linux
   std::string maps;
   bool read = ReadFileToString("/proc/self/maps", &maps);
   if (!read) {
@@ -93,20 +143,18 @@
     std::string end_str(maps.substr(i+1+8, 8));
     uint32_t start = ParseHex(start_str);
     uint32_t end = ParseHex(end_str);
-    CHECK(!(base >= start && base < end)       // start of new within old
-          && !(limit > start && limit < end)  // end of new within old
-          && !(base <= start && limit > end))  // start/end of new includes all of old
-        << StringPrintf("Requested region %08x-%08x overlaps with existing map %08x-%08x\n",
-                        base, limit, start, end)
-        << maps;
+    CheckMapRegion(base, limit, start, end, maps);
     i += 8+1+8;
     i = maps.find('\n', i);
     CHECK(i != std::string::npos) << "Failed to find newline from pos " << i << "\n" << maps;
   }
 #endif
-#endif
 }
 
+#else
+static void CheckMapRequest(byte* addr, size_t length) { }
+#endif
+
 MemMap* MemMap::MapAnonymous(const char* name, byte* addr, size_t length, int prot) {
   CHECK_NE(0U, length);
   CHECK_NE(0, prot);
diff --git a/src/oat_test.cc b/src/oat_test.cc
index 0ca581a..dff360c 100644
--- a/src/oat_test.cc
+++ b/src/oat_test.cc
@@ -21,7 +21,38 @@
 
 namespace art {
 
-class OatTest : public CommonTest {};
+class OatTest : public CommonTest {
+ protected:
+  void CheckMethod(Method* method,
+                   const OatFile::OatMethod& oat_method,
+                   const DexFile* dex_file) {
+    const CompiledMethod* compiled_method =
+        compiler_->GetCompiledMethod(Compiler::MethodReference(dex_file,
+                                                               method->GetDexMethodIndex()));
+
+    if (compiled_method == NULL) {
+      EXPECT_TRUE(oat_method.GetCode() == NULL) << PrettyMethod(method) << " "
+                                                << oat_method.GetCode();
+      EXPECT_EQ(oat_method.GetFrameSizeInBytes(), static_cast<uint32_t>(kStackAlignment));
+      EXPECT_EQ(oat_method.GetCoreSpillMask(), 0U);
+      EXPECT_EQ(oat_method.GetFpSpillMask(), 0U);
+    } else {
+      const void* oat_code = oat_method.GetCode();
+      EXPECT_TRUE(oat_code != NULL) << PrettyMethod(method);
+      uintptr_t oat_code_aligned = RoundDown(reinterpret_cast<uintptr_t>(oat_code), 2);
+      oat_code = reinterpret_cast<const void*>(oat_code_aligned);
+
+      const std::vector<uint8_t>& code = compiled_method->GetCode();
+      size_t code_size = code.size() * sizeof(code[0]);
+      EXPECT_EQ(0, memcmp(oat_code, &code[0], code_size))
+          << PrettyMethod(method) << " " << code_size;
+      CHECK_EQ(0, memcmp(oat_code, &code[0], code_size));
+      EXPECT_EQ(oat_method.GetFrameSizeInBytes(), compiled_method->GetFrameSizeInBytes());
+      EXPECT_EQ(oat_method.GetCoreSpillMask(), compiled_method->GetCoreSpillMask());
+      EXPECT_EQ(oat_method.GetFpSpillMask(), compiled_method->GetFpSpillMask());
+    }
+  }
+};
 
 TEST_F(OatTest, WriteRead) {
   const bool compile = false;  // DISABLED_ due to the time to compile libcore
@@ -64,59 +95,12 @@
 
     size_t method_index = 0;
     for (size_t i = 0; i < klass->NumDirectMethods(); i++, method_index++) {
-      Method* method = klass->GetDirectMethod(i);
-      const OatFile::OatMethod oat_method = oat_class->GetOatMethod(method_index);
-      const CompiledMethod* compiled_method =
-          compiler_->GetCompiledMethod(Compiler::MethodReference(dex_file,
-                                                                 method->GetDexMethodIndex()));
-
-      if (compiled_method == NULL) {
-        EXPECT_TRUE(oat_method.GetCode() == NULL) << PrettyMethod(method) << " " << oat_method.GetCode();
-        EXPECT_EQ(oat_method.GetFrameSizeInBytes(), static_cast<uint32_t>(kStackAlignment));
-        EXPECT_EQ(oat_method.GetCoreSpillMask(), 0U);
-        EXPECT_EQ(oat_method.GetFpSpillMask(), 0U);
-      } else {
-        const void* oat_code = oat_method.GetCode();
-        uintptr_t oat_code_aligned = RoundDown(reinterpret_cast<uintptr_t>(oat_code), 2);
-        oat_code = reinterpret_cast<const void*>(oat_code_aligned);
-
-        const std::vector<uint8_t>& code = compiled_method->GetCode();
-        size_t code_size = code.size() * sizeof(code[0]);
-        EXPECT_EQ(0, memcmp(oat_code, &code[0], code_size))
-            << PrettyMethod(method) << " " << code_size;
-        CHECK_EQ(0, memcmp(oat_code, &code[0], code_size));
-        EXPECT_EQ(oat_method.GetFrameSizeInBytes(), compiled_method->GetFrameSizeInBytes());
-        EXPECT_EQ(oat_method.GetCoreSpillMask(), compiled_method->GetCoreSpillMask());
-        EXPECT_EQ(oat_method.GetFpSpillMask(), compiled_method->GetFpSpillMask());
-      }
+      CheckMethod(klass->GetDirectMethod(i),
+                  oat_class->GetOatMethod(method_index), dex_file);
     }
     for (size_t i = 0; i < num_virtual_methods; i++, method_index++) {
-      Method* method = klass->GetVirtualMethod(i);
-      const OatFile::OatMethod oat_method = oat_class->GetOatMethod(method_index);
-      const CompiledMethod* compiled_method =
-          compiler_->GetCompiledMethod(Compiler::MethodReference(dex_file,
-                                                                 method->GetDexMethodIndex()));
-
-      if (compiled_method == NULL) {
-        EXPECT_TRUE(oat_method.GetCode() == NULL) << PrettyMethod(method) << " " << oat_method.GetCode();
-        EXPECT_EQ(oat_method.GetFrameSizeInBytes(), static_cast<uint32_t>(kStackAlignment));
-        EXPECT_EQ(oat_method.GetCoreSpillMask(), 0U);
-        EXPECT_EQ(oat_method.GetFpSpillMask(), 0U);
-      } else {
-        const void* oat_code = oat_method.GetCode();
-        EXPECT_TRUE(oat_code != NULL) << PrettyMethod(method);
-        uintptr_t oat_code_aligned = RoundDown(reinterpret_cast<uintptr_t>(oat_code), 2);
-        oat_code = reinterpret_cast<const void*>(oat_code_aligned);
-
-        const std::vector<uint8_t>& code = compiled_method->GetCode();
-        size_t code_size = code.size() * sizeof(code[0]);
-        EXPECT_EQ(0, memcmp(oat_code, &code[0], code_size))
-            << PrettyMethod(method) << " " << code_size;
-        CHECK_EQ(0, memcmp(oat_code, &code[0], code_size));
-        EXPECT_EQ(oat_method.GetFrameSizeInBytes(), compiled_method->GetFrameSizeInBytes());
-        EXPECT_EQ(oat_method.GetCoreSpillMask(), compiled_method->GetCoreSpillMask());
-        EXPECT_EQ(oat_method.GetFpSpillMask(), compiled_method->GetFpSpillMask());
-      }
+      CheckMethod(klass->GetVirtualMethod(i),
+                  oat_class->GetOatMethod(method_index), dex_file);
     }
   }
 }