am 2d47df9f: Merge "Add missing error message propagation to ElfFile::SetMap"

* commit '2d47df9fcf5ec53e2afda3ee21a6f7cafb2fd3fb':
  Add missing error message propagation to ElfFile::SetMap
diff --git a/Android.mk b/Android.mk
index 3112ab0..8024a3d 100644
--- a/Android.mk
+++ b/Android.mk
@@ -305,6 +305,8 @@
 ########################################################################
 # oatdump targets
 
+ART_DUMP_OAT_PATH ?= $(OUT_DIR)
+
 .PHONY: dump-oat
 dump-oat: dump-oat-core dump-oat-boot
 
@@ -314,29 +316,29 @@
 .PHONY: dump-oat-core-host
 ifeq ($(ART_BUILD_HOST),true)
 dump-oat-core-host: $(HOST_CORE_IMG_OUT) $(OATDUMP)
-	$(OATDUMP) --image=$(HOST_CORE_IMG_OUT) --output=/tmp/core.host.oatdump.txt --host-prefix=""
-	@echo Output in /tmp/core.host.oatdump.txt
+	$(OATDUMP) --image=$(HOST_CORE_IMG_OUT) --output=$(ART_DUMP_OAT_PATH)/core.host.oatdump.txt --host-prefix=""
+	@echo Output in $(ART_DUMP_OAT_PATH)/core.host.oatdump.txt
 endif
 
 .PHONY: dump-oat-core-target
 ifeq ($(ART_BUILD_TARGET),true)
 dump-oat-core-target: $(TARGET_CORE_IMG_OUT) $(OATDUMP)
-	$(OATDUMP) --image=$(TARGET_CORE_IMG_OUT) --output=/tmp/core.target.oatdump.txt
-	@echo Output in /tmp/core.target.oatdump.txt
+	$(OATDUMP) --image=$(TARGET_CORE_IMG_OUT) --output=$(ART_DUMP_OAT_PATH)/core.target.oatdump.txt
+	@echo Output in $(ART_DUMP_OAT_PATH)/core.target.oatdump.txt
 endif
 
 .PHONY: dump-oat-boot
 ifeq ($(ART_BUILD_TARGET_NDEBUG),true)
 dump-oat-boot: $(TARGET_BOOT_IMG_OUT) $(OATDUMP)
-	$(OATDUMP) --image=$(TARGET_BOOT_IMG_OUT) --output=/tmp/boot.oatdump.txt
-	@echo Output in /tmp/boot.oatdump.txt
+	$(OATDUMP) --image=$(TARGET_BOOT_IMG_OUT) --output=$(ART_DUMP_OAT_PATH)/boot.oatdump.txt
+	@echo Output in $(ART_DUMP_OAT_PATH)/boot.oatdump.txt
 endif
 
 .PHONY: dump-oat-Calculator
 ifeq ($(ART_BUILD_TARGET_NDEBUG),true)
 dump-oat-Calculator: $(TARGET_OUT_APPS)/Calculator.odex $(TARGET_BOOT_IMG_OUT) $(OATDUMP)
-	$(OATDUMP) --oat-file=$< --output=/tmp/Calculator.oatdump.txt
-	@echo Output in /tmp/Calculator.oatdump.txt
+	$(OATDUMP) --oat-file=$< --output=$(ART_DUMP_OAT_PATH)/Calculator.oatdump.txt
+	@echo Output in $(ART_DUMP_OAT_PATH)/Calculator.oatdump.txt
 endif
 
 ########################################################################
diff --git a/build/Android.oat.mk b/build/Android.oat.mk
index f964346..c04b38b 100644
--- a/build/Android.oat.mk
+++ b/build/Android.oat.mk
@@ -26,7 +26,7 @@
 
 # By default, do not run rerun dex2oat if the tool changes.
 # Comment out the | to force dex2oat to rerun on after all changes.
-DEX2OAT_DEPENDENCY := #|
+DEX2OAT_DEPENDENCY := |
 DEX2OAT_DEPENDENCY += $(DEX2OAT)
 DEX2OAT_DEPENDENCY += $(LIBART_COMPILER)
 
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc
index 7225262..d1a9a13 100644
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -1245,84 +1245,87 @@
   const DexFile::TypeId& declaring_type = cu_->dex_file->GetTypeId(target_mid.class_idx_);
   StringPiece tgt_methods_declaring_class(
       cu_->dex_file->StringDataByIdx(declaring_type.descriptor_idx_));
-  if (tgt_methods_declaring_class.starts_with("Ljava/lang/Double;")) {
-    std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
-    if (tgt_method == "long java.lang.Double.doubleToRawLongBits(double)") {
-      return GenInlinedDoubleCvt(info);
-    }
-    if (tgt_method == "double java.lang.Double.longBitsToDouble(long)") {
-      return GenInlinedDoubleCvt(info);
-    }
-  } else if (tgt_methods_declaring_class.starts_with("Ljava/lang/Float;")) {
-    std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
-    if (tgt_method == "int java.lang.Float.floatToRawIntBits(float)") {
-      return GenInlinedFloatCvt(info);
-    }
-    if (tgt_method == "float java.lang.Float.intBitsToFloat(int)") {
-      return GenInlinedFloatCvt(info);
-    }
-  } else if (tgt_methods_declaring_class.starts_with("Ljava/lang/Integer;")) {
-    std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
-    if (tgt_method == "int java.lang.Integer.reverseBytes(int)") {
-      return GenInlinedReverseBytes(info, kWord);
-    }
-  } else if (tgt_methods_declaring_class.starts_with("Ljava/lang/Long;")) {
-    std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
-    if (tgt_method == "long java.lang.Long.reverseBytes(long)") {
-      return GenInlinedReverseBytes(info, kLong);
-    }
-  } else if (tgt_methods_declaring_class.starts_with("Ljava/lang/Math;") ||
-             tgt_methods_declaring_class.starts_with("Ljava/lang/StrictMath;")) {
-    std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
-    if (tgt_method == "int java.lang.Math.abs(int)" ||
-        tgt_method == "int java.lang.StrictMath.abs(int)") {
-      return GenInlinedAbsInt(info);
-    }
-    if (tgt_method == "long java.lang.Math.abs(long)" ||
-        tgt_method == "long java.lang.StrictMath.abs(long)") {
-      return GenInlinedAbsLong(info);
-    }
-    if (tgt_method == "int java.lang.Math.max(int, int)" ||
-        tgt_method == "int java.lang.StrictMath.max(int, int)") {
-      return GenInlinedMinMaxInt(info, false /* is_min */);
-    }
-    if (tgt_method == "int java.lang.Math.min(int, int)" ||
-        tgt_method == "int java.lang.StrictMath.min(int, int)") {
-      return GenInlinedMinMaxInt(info, true /* is_min */);
-    }
-    if (tgt_method == "double java.lang.Math.sqrt(double)" ||
-        tgt_method == "double java.lang.StrictMath.sqrt(double)") {
-      return GenInlinedSqrt(info);
-    }
-  } else if (tgt_methods_declaring_class.starts_with("Ljava/lang/Short;")) {
-    std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
-    if (tgt_method == "short java.lang.Short.reverseBytes(short)") {
-      return GenInlinedReverseBytes(info, kSignedHalf);
-    }
-  } else if (tgt_methods_declaring_class.starts_with("Ljava/lang/String;")) {
-    std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
-    if (tgt_method == "char java.lang.String.charAt(int)") {
-      return GenInlinedCharAt(info);
-    }
-    if (tgt_method == "int java.lang.String.compareTo(java.lang.String)") {
-      return GenInlinedStringCompareTo(info);
-    }
-    if (tgt_method == "boolean java.lang.String.is_empty()") {
-      return GenInlinedStringIsEmptyOrLength(info, true /* is_empty */);
-    }
-    if (tgt_method == "int java.lang.String.index_of(int, int)") {
-      return GenInlinedIndexOf(info, false /* base 0 */);
-    }
-    if (tgt_method == "int java.lang.String.index_of(int)") {
-      return GenInlinedIndexOf(info, true /* base 0 */);
-    }
-    if (tgt_method == "int java.lang.String.length()") {
-      return GenInlinedStringIsEmptyOrLength(info, false /* is_empty */);
-    }
-  } else if (tgt_methods_declaring_class.starts_with("Ljava/lang/Thread;")) {
-    std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
-    if (tgt_method == "java.lang.Thread java.lang.Thread.currentThread()") {
-      return GenInlinedCurrentThread(info);
+  if (tgt_methods_declaring_class.starts_with("Ljava/lang/")) {
+    tgt_methods_declaring_class.remove_prefix(sizeof("Ljava/lang/") - 1);
+    if (tgt_methods_declaring_class.starts_with("Double;")) {
+      std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
+      if (tgt_method == "long java.lang.Double.doubleToRawLongBits(double)") {
+        return GenInlinedDoubleCvt(info);
+      }
+      if (tgt_method == "double java.lang.Double.longBitsToDouble(long)") {
+        return GenInlinedDoubleCvt(info);
+      }
+    } else if (tgt_methods_declaring_class.starts_with("Float;")) {
+      std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
+      if (tgt_method == "int java.lang.Float.floatToRawIntBits(float)") {
+        return GenInlinedFloatCvt(info);
+      }
+      if (tgt_method == "float java.lang.Float.intBitsToFloat(int)") {
+        return GenInlinedFloatCvt(info);
+      }
+    } else if (tgt_methods_declaring_class.starts_with("Integer;")) {
+      std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
+      if (tgt_method == "int java.lang.Integer.reverseBytes(int)") {
+        return GenInlinedReverseBytes(info, kWord);
+      }
+    } else if (tgt_methods_declaring_class.starts_with("Long;")) {
+      std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
+      if (tgt_method == "long java.lang.Long.reverseBytes(long)") {
+        return GenInlinedReverseBytes(info, kLong);
+      }
+    } else if (tgt_methods_declaring_class.starts_with("Math;") ||
+               tgt_methods_declaring_class.starts_with("StrictMath;")) {
+      std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
+      if (tgt_method == "int java.lang.Math.abs(int)" ||
+          tgt_method == "int java.lang.StrictMath.abs(int)") {
+        return GenInlinedAbsInt(info);
+      }
+      if (tgt_method == "long java.lang.Math.abs(long)" ||
+          tgt_method == "long java.lang.StrictMath.abs(long)") {
+        return GenInlinedAbsLong(info);
+      }
+      if (tgt_method == "int java.lang.Math.max(int, int)" ||
+          tgt_method == "int java.lang.StrictMath.max(int, int)") {
+        return GenInlinedMinMaxInt(info, false /* is_min */);
+      }
+      if (tgt_method == "int java.lang.Math.min(int, int)" ||
+          tgt_method == "int java.lang.StrictMath.min(int, int)") {
+        return GenInlinedMinMaxInt(info, true /* is_min */);
+      }
+      if (tgt_method == "double java.lang.Math.sqrt(double)" ||
+          tgt_method == "double java.lang.StrictMath.sqrt(double)") {
+        return GenInlinedSqrt(info);
+      }
+    } else if (tgt_methods_declaring_class.starts_with("Short;")) {
+      std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
+      if (tgt_method == "short java.lang.Short.reverseBytes(short)") {
+        return GenInlinedReverseBytes(info, kSignedHalf);
+      }
+    } else if (tgt_methods_declaring_class.starts_with("String;")) {
+      std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
+      if (tgt_method == "char java.lang.String.charAt(int)") {
+        return GenInlinedCharAt(info);
+      }
+      if (tgt_method == "int java.lang.String.compareTo(java.lang.String)") {
+        return GenInlinedStringCompareTo(info);
+      }
+      if (tgt_method == "boolean java.lang.String.is_empty()") {
+        return GenInlinedStringIsEmptyOrLength(info, true /* is_empty */);
+      }
+      if (tgt_method == "int java.lang.String.index_of(int, int)") {
+        return GenInlinedIndexOf(info, false /* base 0 */);
+      }
+      if (tgt_method == "int java.lang.String.index_of(int)") {
+        return GenInlinedIndexOf(info, true /* base 0 */);
+      }
+      if (tgt_method == "int java.lang.String.length()") {
+        return GenInlinedStringIsEmptyOrLength(info, false /* is_empty */);
+      }
+    } else if (tgt_methods_declaring_class.starts_with("Thread;")) {
+      std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
+      if (tgt_method == "java.lang.Thread java.lang.Thread.currentThread()") {
+        return GenInlinedCurrentThread(info);
+      }
     }
   } else if (tgt_methods_declaring_class.starts_with("Llibcore/io/Memory;")) {
     std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index b9716d5..90276c2 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -715,14 +715,25 @@
         if (image_root_object->IsObjectArray()) {
           Indenter indent2_filter(indent1_os.rdbuf(), kIndentChar, kIndentBy1Count);
           std::ostream indent2_os(&indent2_filter);
-          // TODO: replace down_cast with AsObjectArray (g++ currently has a problem with this)
           mirror::ObjectArray<mirror::Object>* image_root_object_array
-              = down_cast<mirror::ObjectArray<mirror::Object>*>(image_root_object);
-          //  = image_root_object->AsObjectArray<Object>();
+              = image_root_object->AsObjectArray<mirror::Object>();
           for (int i = 0; i < image_root_object_array->GetLength(); i++) {
             mirror::Object* value = image_root_object_array->Get(i);
+            size_t run = 0;
+            for (int32_t j = i + 1; j < image_root_object_array->GetLength(); j++) {
+              if (value == image_root_object_array->Get(j)) {
+                run++;
+              } else {
+                break;
+              }
+            }
+            if (run == 0) {
+              indent2_os << StringPrintf("%d: ", i);
+            } else {
+              indent2_os << StringPrintf("%d to %zd: ", i, i + run);
+              i = i + run;
+            }
             if (value != NULL) {
-              indent2_os << i << ": ";
               PrettyObjectValue(indent2_os, value->GetClass(), value);
             } else {
               indent2_os << i << ": null\n";
diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S
index 9a853d0..1a058ea 100644
--- a/runtime/arch/arm/quick_entrypoints_arm.S
+++ b/runtime/arch/arm/quick_entrypoints_arm.S
@@ -69,12 +69,24 @@
 .macro RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
     add sp, #4               @ bottom word holds Method*
     pop {r5-r8, r10-r11, lr} @ 7 words of callee saves
+    .cfi_restore r5
+    .cfi_restore r6
+    .cfi_restore r7
+    .cfi_restore r8
+    .cfi_restore r10
+    .cfi_restore r11
     .cfi_adjust_cfa_offset -32
 .endm
 
 .macro RESTORE_REF_ONLY_CALLEE_SAVE_FRAME_AND_RETURN
     add sp, #4               @ bottom word holds Method*
     pop {r5-r8, r10-r11, lr} @ 7 words of callee saves
+    .cfi_restore r5
+    .cfi_restore r6
+    .cfi_restore r7
+    .cfi_restore r8
+    .cfi_restore r10
+    .cfi_restore r11
     .cfi_adjust_cfa_offset -32
     bx  lr                   @ return
 .endm
@@ -86,7 +98,6 @@
 .macro SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
     push {r1-r3, r5-r8, r10-r11, lr}  @ 10 words of callee saves
     .save {r1-r3, r5-r8, r10-r11, lr}
-    .cfi_adjust_cfa_offset 40
     .cfi_rel_offset r1, 0
     .cfi_rel_offset r2, 4
     .cfi_rel_offset r3, 8
@@ -97,6 +108,7 @@
     .cfi_rel_offset r10, 28
     .cfi_rel_offset r11, 32
     .cfi_rel_offset lr, 36
+    .cfi_adjust_cfa_offset 40
     sub sp, #8                        @ 2 words of space, bottom word will hold Method*
     .pad #8
     .cfi_adjust_cfa_offset 8
@@ -105,6 +117,15 @@
 .macro RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
     add  sp, #8                      @ rewind sp
     pop {r1-r3, r5-r8, r10-r11, lr}  @ 10 words of callee saves
+    .cfi_restore r1
+    .cfi_restore r2
+    .cfi_restore r3
+    .cfi_restore r5
+    .cfi_restore r6
+    .cfi_restore r7
+    .cfi_restore r8
+    .cfi_restore r10
+    .cfi_restore r11
     .cfi_adjust_cfa_offset -48
 .endm
 
@@ -285,6 +306,11 @@
     ldr    ip, [sp, #24]                   @ load the result pointer
     strd   r0, [ip]                        @ store r0/r1 into result pointer
     pop    {r0, r4, r5, r9, r11, lr}       @ restore spill regs
+    .cfi_restore r0
+    .cfi_restore r4
+    .cfi_restore r5
+    .cfi_restore r9
+    .cfi_restore lr
     .cfi_adjust_cfa_offset -24
     bx     lr
 END art_quick_invoke_stub
@@ -413,6 +439,8 @@
     add sp, #4
     .cfi_adjust_cfa_offset -4
     pop {r0-r1, lr}
+    .cfi_restore r0
+    .cfi_restore r1
     SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // save all registers as basis for long jump context
     mov r2, r9                      @ pass Thread::Current
     mov r3, sp                      @ pass SP
@@ -689,6 +717,7 @@
     .cfi_rel_offset r9, 0
     bl     artSet64StaticFromCode        @ (field_idx, referrer, new_val, Thread*, SP)
     add    sp, #16                       @ release out args
+    .cfi_adjust_cfa_offset -16
     RESTORE_REF_ONLY_CALLEE_SAVE_FRAME   @ TODO: we can clearly save an add here
     RETURN_IF_RESULT_IS_ZERO
     DELIVER_PENDING_EXCEPTION
@@ -1137,6 +1166,8 @@
     mov   r2, r0         @ link register saved by instrumentation
     mov   lr, r1         @ r1 is holding link register if we're to bounce to deoptimize
     pop   {r0, r1}       @ restore return value
+    .cfi_restore r0
+    .cfi_restore r1
     add sp, #32          @ remove callee save frame
     .cfi_adjust_cfa_offset -32
     bx    r2             @ return
@@ -1187,6 +1218,8 @@
     mov     r1,r10
     pop     {r9 - r10}
     .cfi_adjust_cfa_offset -8
+    .cfi_restore r9
+    .cfi_restore r10
     bx      lr
 END art_quick_mul_long
 
diff --git a/runtime/arch/mips/quick_entrypoints_mips.S b/runtime/arch/mips/quick_entrypoints_mips.S
index 451b1bb..8862711 100644
--- a/runtime/arch/mips/quick_entrypoints_mips.S
+++ b/runtime/arch/mips/quick_entrypoints_mips.S
@@ -89,28 +89,46 @@
 
 .macro RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
     lw     $ra, 60($sp)
+    .cfi_restore 31
     lw     $s8, 56($sp)
+    .cfi_restore 30
     lw     $gp, 52($sp)
+    .cfi_restore 28
     lw     $s7, 48($sp)
+    .cfi_restore 23
     lw     $s6, 44($sp)
+    .cfi_restore 22
     lw     $s5, 40($sp)
+    .cfi_restore 21
     lw     $s4, 36($sp)
+    .cfi_restore 20
     lw     $s3, 32($sp)
+    .cfi_restore 19
     lw     $s2, 28($sp)
+    .cfi_restore 18
     addiu  $sp, $sp, 64
     .cfi_adjust_cfa_offset -64
 .endm
 
 .macro RESTORE_REF_ONLY_CALLEE_SAVE_FRAME_AND_RETURN
     lw     $ra, 60($sp)
+    .cfi_restore 31
     lw     $s8, 56($sp)
+    .cfi_restore 30
     lw     $gp, 52($sp)
+    .cfi_restore 28
     lw     $s7, 48($sp)
+    .cfi_restore 23
     lw     $s6, 44($sp)
+    .cfi_restore 22
     lw     $s5, 40($sp)
+    .cfi_restore 21
     lw     $s4, 36($sp)
+    .cfi_restore 20
     lw     $s3, 32($sp)
+    .cfi_restore 19
     lw     $s2, 28($sp)
+    .cfi_restore 18
     jr     $ra
     addiu  $sp, $sp, 64
     .cfi_adjust_cfa_offset -64
@@ -153,17 +171,29 @@
 
 .macro RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
     lw     $ra, 60($sp)
+    .cfi_restore 31
     lw     $s8, 56($sp)
+    .cfi_restore 30
     lw     $gp, 52($sp)
+    .cfi_restore 28
     lw     $s7, 48($sp)
+    .cfi_restore 23
     lw     $s6, 44($sp)
+    .cfi_restore 22
     lw     $s5, 40($sp)
+    .cfi_restore 21
     lw     $s4, 36($sp)
+    .cfi_restore 20
     lw     $s3, 32($sp)
+    .cfi_restore 19
     lw     $s2, 28($sp)
+    .cfi_restore 18
     lw     $a3, 12($sp)
+    .cfi_restore 7
     lw     $a2, 8($sp)
+    .cfi_restore 6
     lw     $a1, 4($sp)
+    .cfi_restore 5
     addiu  $sp, $sp, 64           # pop frame
     .cfi_adjust_cfa_offset -64
 .endm
@@ -463,9 +493,13 @@
     sw    $zero, 0($sp)         # store NULL for method* at bottom of frame
     move  $sp, $fp              # restore the stack
     lw    $s0, 0($sp)
+    .cfi_restore 16
     lw    $s1, 4($sp)
+    .cfi_restore 17
     lw    $fp, 8($sp)
+    .cfi_restore 30
     lw    $ra, 12($sp)
+    .cfi_restore 31
     addiu $sp, $sp, 16
     .cfi_adjust_cfa_offset -16
     lw    $t0, 16($sp)          # get result pointer
diff --git a/runtime/arch/x86/quick_entrypoints_x86.S b/runtime/arch/x86/quick_entrypoints_x86.S
index 6fe4993..ee78d45 100644
--- a/runtime/arch/x86/quick_entrypoints_x86.S
+++ b/runtime/arch/x86/quick_entrypoints_x86.S
@@ -16,14 +16,19 @@
 
 #include "asm_support_x86.S"
 
+// For x86, the CFA is esp+4, the address above the pushed return address on the stack.
+
     /*
      * Macro that sets up the callee save frame to conform with
      * Runtime::CreateCalleeSaveMethod(kSaveAll)
      */
 MACRO0(SETUP_SAVE_ALL_CALLEE_SAVE_FRAME)
     PUSH edi  // Save callee saves (ebx is saved/restored by the upcall)
+    .cfi_rel_offset edi, -8
     PUSH esi
+    .cfi_rel_offset esi, -12
     PUSH ebp
+    .cfi_rel_offset ebp, -16
     subl  MACRO_LITERAL(16), %esp  // Grow stack by 4 words, bottom word will hold Method*
     .cfi_adjust_cfa_offset 16
 END_MACRO
@@ -34,8 +39,11 @@
      */
 MACRO0(SETUP_REF_ONLY_CALLEE_SAVE_FRAME)
     PUSH edi  // Save callee saves (ebx is saved/restored by the upcall)
+     .cfi_rel_offset edi, -8
     PUSH esi
+    .cfi_rel_offset esi, -12
     PUSH ebp
+     .cfi_rel_offset ebp, -16
     subl  MACRO_LITERAL(16), %esp  // Grow stack by 4 words, bottom word will hold Method*
     .cfi_adjust_cfa_offset 16
 END_MACRO
@@ -43,8 +51,11 @@
 MACRO0(RESTORE_REF_ONLY_CALLEE_SAVE_FRAME)
     addl MACRO_LITERAL(16), %esp  // Unwind stack up to return address
     POP ebp  // Restore callee saves (ebx is saved/restored by the upcall)
+    .cfi_restore ebp
     POP esi
+    .cfi_restore esi
     POP edi
+    .cfi_restore edi
     .cfi_adjust_cfa_offset -28
 END_MACRO
 
@@ -54,23 +65,36 @@
      */
 MACRO0(SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME)
     PUSH edi  // Save callee saves
+    .cfi_rel_offset edi, -8
     PUSH esi
+    .cfi_rel_offset esi, -12
     PUSH ebp
+    .cfi_rel_offset ebp, -16
     PUSH ebx  // Save args
+    .cfi_rel_offset ebx, -20
     PUSH edx
+    .cfi_rel_offset edx, -24
     PUSH ecx
+    .cfi_rel_offset ecx, -28
     PUSH eax   // Align stack, eax will be clobbered by Method*
+    .cfi_rel_offset eax, -28
 END_MACRO
 
 MACRO0(RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME)
     addl MACRO_LITERAL(4), %esp  // Remove padding
     .cfi_adjust_cfa_offset -4
     POP ecx  // Restore args except eax
+    .cfi_restore ecx
     POP edx
+    .cfi_restore edx
     POP ebx
+    .cfi_restore ebx
     POP ebp  // Restore callee saves
+    .cfi_restore ebp
     POP esi
+    .cfi_restore esi
     POP edi
+    .cfi_restore edi
 END_MACRO
 
     /*
@@ -188,12 +212,19 @@
     // Set up the callee save frame to conform with Runtime::CreateCalleeSaveMethod(kRefsAndArgs)
     // return address
     PUSH edi
+    .cfi_rel_offset edi, -8
     PUSH esi
+    .cfi_rel_offset esi, -12
     PUSH ebp
-    PUSH ebx
+    .cfi_rel_offset ebp, -16
+    PUSH ebx  // Save args
+    .cfi_rel_offset ebx, -20
     PUSH edx
+    .cfi_rel_offset edx, -24
     PUSH ecx
-    PUSH eax   // <-- callee save Method* to go here
+    .cfi_rel_offset ecx, -28
+    PUSH eax    // <-- callee save Method* to go here
+    .cfi_rel_offset eax, -32
     movl %esp, %edx  // remember SP
     // Outgoing argument set up
     subl MACRO_LITERAL(12), %esp  // alignment padding
@@ -209,11 +240,16 @@
     movl %edx, %edi               // save code pointer in EDI
     addl MACRO_LITERAL(36), %esp  // Pop arguments skip eax
     .cfi_adjust_cfa_offset -36
-    POP ecx                       // Restore args
+    POP ecx  // Restore args except eax
+    .cfi_restore ecx
     POP edx
+    .cfi_restore edx
     POP ebx
-    POP ebp  // Restore callee saves.
+    .cfi_restore ebx
+    POP ebp  // Restore callee saves
+    .cfi_restore ebp
     POP esi
+    .cfi_restore esi
     // Swap EDI callee save with code pointer.
     xchgl %edi, (%esp)
     testl %eax, %eax              // Branch forward if exception pending.
@@ -248,7 +284,9 @@
      */
 DEFINE_FUNCTION art_quick_invoke_stub
     PUSH ebp                      // save ebp
+    .cfi_rel_offset ebp, -8
     PUSH ebx                      // save ebx
+    .cfi_rel_offset ebx, -12
     mov %esp, %ebp                // copy value of stack pointer into base pointer
     .cfi_def_cfa_register ebp
     mov 20(%ebp), %ebx            // get arg array size
@@ -269,8 +307,11 @@
     mov 12(%esp), %ebx            // copy arg3 into ebx
     call *METHOD_CODE_OFFSET(%eax) // call the method
     mov %ebp, %esp                // restore stack pointer
+    .cfi_def_cfa_register esp
     POP ebx                       // pop ebx
+    .cfi_restore ebx
     POP ebp                       // pop ebp
+    .cfi_restore ebp
     mov 20(%esp), %ecx            // get result pointer
     cmpl LITERAL(68), 24(%esp)    // test if result type char == 'D'
     je return_double_quick
@@ -495,7 +536,9 @@
 DEFINE_FUNCTION art_quick_check_cast
     PUSH eax                     // alignment padding
     PUSH ecx                     // pass arg2 - obj->klass
+    .cfi_rel_offset ecx, -12
     PUSH eax                     // pass arg1 - checked class
+    .cfi_rel_offset eax, -16
     call SYMBOL(artIsAssignableFromCode)  // (Class* klass, Class* ref_klass)
     testl %eax, %eax
     jz 1f                         // jump forward if not assignable
@@ -504,7 +547,9 @@
     ret
 1:
     POP eax                       // pop arguments
+    .cfi_restore eax
     POP ecx
+    .cfi_restore ecx
     addl LITERAL(4), %esp
     .cfi_adjust_cfa_offset -12
     SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // save all registers as basis for long jump context
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index bdcf6ac..0eecd28 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -3489,9 +3489,9 @@
       recent_allocation_records_ = new AllocRecord[gAllocRecordMax];
       CHECK(recent_allocation_records_ != NULL);
     }
-    Runtime::Current()->InstrumentQuickAllocEntryPoints();
+    Runtime::Current()->GetInstrumentation()->InstrumentQuickAllocEntryPoints();
   } else {
-    Runtime::Current()->UninstrumentQuickAllocEntryPoints();
+    Runtime::Current()->GetInstrumentation()->UninstrumentQuickAllocEntryPoints();
     delete[] recent_allocation_records_;
     recent_allocation_records_ = NULL;
   }
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 804c669..de3ab0e 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -237,7 +237,7 @@
   CHECK_NE(max_allowed_footprint_, 0U);
 
   if (running_on_valgrind_) {
-    Runtime::Current()->InstrumentQuickAllocEntryPoints();
+    Runtime::Current()->GetInstrumentation()->InstrumentQuickAllocEntryPoints();
   }
 
   if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 7d2441b..91909e4 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -300,6 +300,10 @@
     card_table_->MarkCard(dst);
   }
 
+  void WriteBarrierEveryFieldOf(const mirror::Object* obj) {
+    card_table_->MarkCard(obj);
+  }
+
   accounting::CardTable* GetCardTable() const {
     return card_table_.get();
   }
diff --git a/runtime/indenter.h b/runtime/indenter.h
index c432e1b..d055d4e 100644
--- a/runtime/indenter.h
+++ b/runtime/indenter.h
@@ -17,6 +17,7 @@
 #ifndef ART_RUNTIME_INDENTER_H_
 #define ART_RUNTIME_INDENTER_H_
 
+#include "base/logging.h"
 #include "base/macros.h"
 #include <streambuf>
 
@@ -30,16 +31,28 @@
 
  private:
   int_type overflow(int_type c) {
-    if (c != std::char_traits<char>::eof()) {
-      if (indent_next_) {
-        for (size_t i = 0; i < count_; ++i) {
-          out_sbuf_->sputc(text_);
+    if (UNLIKELY(c == std::char_traits<char>::eof())) {
+      out_sbuf_->pubsync();
+      return c;
+    }
+    if (indent_next_) {
+      for (size_t i = 0; i < count_; ++i) {
+        int_type r = out_sbuf_->sputc(text_);
+        if (UNLIKELY(r != text_)) {
+          out_sbuf_->pubsync();
+          r = out_sbuf_->sputc(text_);
+          CHECK_EQ(r, text_) << "Error writing to buffer. Disk full?";
         }
       }
-      out_sbuf_->sputc(c);
-      indent_next_ = (c == '\n');
     }
-    return std::char_traits<char>::not_eof(c);
+    indent_next_ = (c == '\n');
+    int_type r = out_sbuf_->sputc(c);
+    if (UNLIKELY(r != c)) {
+      out_sbuf_->pubsync();
+      r = out_sbuf_->sputc(c);
+      CHECK_EQ(r, c) << "Error writing to buffer. Disk full?";
+    }
+    return r;
   }
 
   int sync() {
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index 8cf486f..0f4fa4e 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -39,6 +39,9 @@
 #include "thread_list.h"
 
 namespace art {
+
+extern void SetQuickAllocEntryPointsInstrumented(bool instrumented);
+
 namespace instrumentation {
 
 // Do we want to deoptimize for method entry and exit listeners or just try to intercept
@@ -391,6 +394,55 @@
   }
 }
 
+static void ResetQuickAllocEntryPointsForThread(Thread* thread, void* arg) {
+  thread->ResetQuickAllocEntryPointsForThread();
+}
+
+void Instrumentation::InstrumentQuickAllocEntryPoints() {
+  // TODO: the read of quick_alloc_entry_points_instrumentation_counter_ is racey and this code
+  //       should be guarded by a lock.
+  DCHECK_GE(quick_alloc_entry_points_instrumentation_counter_, 0U);
+  bool enable_instrumentation = (quick_alloc_entry_points_instrumentation_counter_ == 0);
+  quick_alloc_entry_points_instrumentation_counter_++;
+  if (enable_instrumentation) {
+    // Instrumentation wasn't enabled so enable it.
+    SetQuickAllocEntryPointsInstrumented(true);
+    Runtime* runtime = Runtime::Current();
+    if (runtime->IsStarted()) {
+      ThreadList* tl = runtime->GetThreadList();
+      Thread* self = Thread::Current();
+      tl->SuspendAll();
+      {
+        MutexLock mu(self, *Locks::thread_list_lock_);
+        tl->ForEach(ResetQuickAllocEntryPointsForThread, NULL);
+      }
+      tl->ResumeAll();
+    }
+  }
+}
+
+void Instrumentation::UninstrumentQuickAllocEntryPoints() {
+  // TODO: the read of quick_alloc_entry_points_instrumentation_counter_ is racey and this code
+  //       should be guarded by a lock.
+  DCHECK_GT(quick_alloc_entry_points_instrumentation_counter_, 0U);
+  quick_alloc_entry_points_instrumentation_counter_--;
+  bool disable_instrumentation = (quick_alloc_entry_points_instrumentation_counter_ == 0);
+  if (disable_instrumentation) {
+    SetQuickAllocEntryPointsInstrumented(false);
+    Runtime* runtime = Runtime::Current();
+    if (runtime->IsStarted()) {
+      ThreadList* tl = Runtime::Current()->GetThreadList();
+      Thread* self = Thread::Current();
+      tl->SuspendAll();
+      {
+        MutexLock mu(self, *Locks::thread_list_lock_);
+        tl->ForEach(ResetQuickAllocEntryPointsForThread, NULL);
+      }
+      tl->ResumeAll();
+    }
+  }
+}
+
 void Instrumentation::UpdateMethodsCode(mirror::ArtMethod* method, const void* code) const {
   if (LIKELY(!instrumentation_stubs_installed_)) {
     method->SetEntryPointFromCompiledCode(code);
diff --git a/runtime/instrumentation.h b/runtime/instrumentation.h
index 7a0aaf7..25a4eec 100644
--- a/runtime/instrumentation.h
+++ b/runtime/instrumentation.h
@@ -104,7 +104,8 @@
       have_method_entry_listeners_(false), have_method_exit_listeners_(false),
       have_method_unwind_listeners_(false), have_dex_pc_listeners_(false),
       have_exception_caught_listeners_(false),
-      interpreter_handler_table_(kMainHandlerTable) {}
+      interpreter_handler_table_(kMainHandlerTable),
+      quick_alloc_entry_points_instrumentation_counter_(0) {}
 
   // Add a listener to be notified of the masked together sent of instrumentation events. This
   // suspend the runtime to install stubs. You are expected to hold the mutator lock as a proxy
@@ -123,6 +124,9 @@
     return interpreter_handler_table_;
   }
 
+  void InstrumentQuickAllocEntryPoints() LOCKS_EXCLUDED(Locks::thread_list_lock_);
+  void UninstrumentQuickAllocEntryPoints() LOCKS_EXCLUDED(Locks::thread_list_lock_);
+
   // Update the code of a method respecting any installed stubs.
   void UpdateMethodsCode(mirror::ArtMethod* method, const void* code) const;
 
@@ -289,9 +293,14 @@
   std::list<InstrumentationListener*> dex_pc_listeners_ GUARDED_BY(Locks::mutator_lock_);
   std::list<InstrumentationListener*> exception_caught_listeners_ GUARDED_BY(Locks::mutator_lock_);
 
-  // Current interpreter handler table. This is updated each time the thread state flags are modified.
+  // Current interpreter handler table. This is updated each time the thread state flags are
+  // modified.
   InterpreterHandlerTable interpreter_handler_table_;
 
+  // Greater than 0 if quick alloc entry points instrumented.
+  // TODO: The access and changes to this is racy and should be guarded by a lock.
+  size_t quick_alloc_entry_points_instrumentation_counter_;
+
   DISALLOW_COPY_AND_ASSIGN(Instrumentation);
 };
 
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index bd187c1..87d02c9 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -40,48 +40,39 @@
 namespace mirror {
 
 Object* Object::Clone(Thread* self) {
-  Class* c = GetClass();
+  mirror::Class* c = GetClass();
   DCHECK(!c->IsClassClass());
-
   // Object::SizeOf gets the right size even if we're an array.
   // Using c->AllocObject() here would be wrong.
   size_t num_bytes = SizeOf();
   gc::Heap* heap = Runtime::Current()->GetHeap();
-  SirtRef<Object> copy(self, heap->AllocObject(self, c, num_bytes));
-  if (copy.get() == NULL) {
-    return NULL;
+  SirtRef<mirror::Object> sirt_this(self, this);
+  Object* copy = heap->AllocObject(self, c, num_bytes);
+  if (UNLIKELY(copy == nullptr)) {
+    return nullptr;
   }
-
   // Copy instance data.  We assume memcpy copies by words.
   // TODO: expose and use move32.
-  byte* src_bytes = reinterpret_cast<byte*>(this);
-  byte* dst_bytes = reinterpret_cast<byte*>(copy.get());
+  byte* src_bytes = reinterpret_cast<byte*>(sirt_this.get());
+  byte* dst_bytes = reinterpret_cast<byte*>(copy);
   size_t offset = sizeof(Object);
   memcpy(dst_bytes + offset, src_bytes + offset, num_bytes - offset);
-
   // Perform write barriers on copied object references.
+  c = copy->GetClass();  // Re-read Class in case it moved.
   if (c->IsArrayClass()) {
     if (!c->GetComponentType()->IsPrimitive()) {
       const ObjectArray<Object>* array = copy->AsObjectArray<Object>();
-      heap->WriteBarrierArray(copy.get(), 0, array->GetLength());
+      heap->WriteBarrierArray(copy, 0, array->GetLength());
     }
   } else {
-    for (const Class* klass = c; klass != NULL; klass = klass->GetSuperClass()) {
-      size_t num_reference_fields = klass->NumReferenceInstanceFields();
-      for (size_t i = 0; i < num_reference_fields; ++i) {
-        ArtField* field = klass->GetInstanceField(i);
-        MemberOffset field_offset = field->GetOffset();
-        const Object* ref = copy->GetFieldObject<const Object*>(field_offset, false);
-        heap->WriteBarrierField(copy.get(), field_offset, ref);
-      }
-    }
+    heap->WriteBarrierEveryFieldOf(copy);
   }
-
   if (c->IsFinalizable()) {
-    heap->AddFinalizerReference(Thread::Current(), copy.get());
+    SirtRef<mirror::Object> sirt_copy(self, copy);
+    heap->AddFinalizerReference(self, copy);
+    return sirt_copy.get();
   }
-
-  return copy.get();
+  return copy;
 }
 
 int32_t Object::GenerateIdentityHashCode() {
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 34cf45b..53c9b2e 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -102,8 +102,7 @@
       use_compile_time_class_path_(false),
       main_thread_group_(NULL),
       system_thread_group_(NULL),
-      system_class_loader_(NULL),
-      quick_alloc_entry_points_instrumentation_counter_(0) {
+      system_class_loader_(NULL) {
   for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
     callee_save_methods_[i] = NULL;
   }
@@ -1077,9 +1076,9 @@
     GetStats()->Clear(~0);
     // TODO: wouldn't it make more sense to clear _all_ threads' stats?
     Thread::Current()->GetStats()->Clear(~0);
-    InstrumentQuickAllocEntryPoints();
+    GetInstrumentation()->InstrumentQuickAllocEntryPoints();
   } else {
-    UninstrumentQuickAllocEntryPoints();
+    GetInstrumentation()->UninstrumentQuickAllocEntryPoints();
   }
   stats_enabled_ = new_state;
 }
@@ -1336,46 +1335,4 @@
   compile_time_class_paths_.Put(class_loader, class_path);
 }
 
-static void ResetQuickAllocEntryPointsForThread(Thread* thread, void* arg) {
-  thread->ResetQuickAllocEntryPointsForThread();
-}
-
-void SetQuickAllocEntryPointsInstrumented(bool instrumented);
-
-void Runtime::InstrumentQuickAllocEntryPoints() {
-  ThreadList* tl = thread_list_;
-  Thread* self = Thread::Current();
-  tl->SuspendAll();
-  {
-    MutexLock mu(self, *Locks::runtime_shutdown_lock_);
-    MutexLock mu2(self, *Locks::thread_list_lock_);
-    DCHECK_GE(quick_alloc_entry_points_instrumentation_counter_, 0);
-    int old_counter = quick_alloc_entry_points_instrumentation_counter_++;
-    if (old_counter == 0) {
-      // If it was disabled, enable it.
-      SetQuickAllocEntryPointsInstrumented(true);
-      tl->ForEach(ResetQuickAllocEntryPointsForThread, NULL);
-    }
-  }
-  tl->ResumeAll();
-}
-
-void Runtime::UninstrumentQuickAllocEntryPoints() {
-  ThreadList* tl = thread_list_;
-  Thread* self = Thread::Current();
-  tl->SuspendAll();
-  {
-    MutexLock mu(self, *Locks::runtime_shutdown_lock_);
-    MutexLock mu2(self, *Locks::thread_list_lock_);
-    DCHECK_GT(quick_alloc_entry_points_instrumentation_counter_, 0);
-    int new_counter = --quick_alloc_entry_points_instrumentation_counter_;
-    if (new_counter == 0) {
-      // Disable it if the counter becomes zero.
-      SetQuickAllocEntryPointsInstrumented(false);
-      tl->ForEach(ResetQuickAllocEntryPointsForThread, NULL);
-    }
-  }
-  tl->ResumeAll();
-}
-
 }  // namespace art
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 0ce2642..24b4c87 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -442,9 +442,6 @@
   const std::vector<const DexFile*>& GetCompileTimeClassPath(jobject class_loader);
   void SetCompileTimeClassPath(jobject class_loader, std::vector<const DexFile*>& class_path);
 
-  void InstrumentQuickAllocEntryPoints();
-  void UninstrumentQuickAllocEntryPoints();
-
  private:
   static void InitPlatformSignalHandlers();
 
@@ -567,8 +564,6 @@
   // As returned by ClassLoader.getSystemClassLoader().
   jobject system_class_loader_;
 
-  int quick_alloc_entry_points_instrumentation_counter_;
-
   DISALLOW_COPY_AND_ASSIGN(Runtime);
 };