Merge "Fix offset math for upcalls on x86" into ics-mr1-plus-art
diff --git a/src/class_linker.cc b/src/class_linker.cc
index e26677d..10e2e5e 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -570,7 +570,7 @@
 
   Heap* heap = Runtime::Current()->GetHeap();
   std::string boot_image_option_string("--boot-image=");
-  boot_image_option_string += heap->GetSpaces()[0]->AsImageSpace()->GetImageFilename();
+  boot_image_option_string += heap->GetImageSpace()->GetImageFilename();
   const char* boot_image_option = boot_image_option_string.c_str();
 
   std::string dex_file_option_string("--dex-file=");
@@ -875,40 +875,33 @@
   CHECK(!init_done_);
 
   Heap* heap = Runtime::Current()->GetHeap();
-  const std::vector<Space*>& spaces = heap->GetSpaces();
-  for (size_t i = 0; i < spaces.size(); ++i) {
-    if (spaces[i]->IsImageSpace()) {
-      ImageSpace* space = spaces[i]->AsImageSpace();
-      OatFile* oat_file = OpenOat(space);
-      CHECK(oat_file != NULL) << "Failed to open oat file for image";
-      Object* dex_caches_object = space->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches);
-      ObjectArray<DexCache>* dex_caches = dex_caches_object->AsObjectArray<DexCache>();
+  ImageSpace* space = heap->GetImageSpace();
+  OatFile* oat_file = OpenOat(space);
+  CHECK(oat_file != NULL) << "Failed to open oat file for image";
+  Object* dex_caches_object = space->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches);
+  ObjectArray<DexCache>* dex_caches = dex_caches_object->AsObjectArray<DexCache>();
 
-      if (i == 0) {
-        // Special case of setting up the String class early so that we can test arbitrary objects
-        // as being Strings or not
-        Class* java_lang_String = space->GetImageHeader().GetImageRoot(ImageHeader::kClassRoots)
-            ->AsObjectArray<Class>()->Get(kJavaLangString);
-        String::SetClass(java_lang_String);
-      }
+  // Special case of setting up the String class early so that we can test arbitrary objects
+  // as being Strings or not
+  Class* java_lang_String = space->GetImageHeader().GetImageRoot(ImageHeader::kClassRoots)
+      ->AsObjectArray<Class>()->Get(kJavaLangString);
+  String::SetClass(java_lang_String);
 
-      CHECK_EQ(oat_file->GetOatHeader().GetDexFileCount(),
-               static_cast<uint32_t>(dex_caches->GetLength()));
-      for (int i = 0; i < dex_caches->GetLength(); i++) {
-        SirtRef<DexCache> dex_cache(dex_caches->Get(i));
-        const std::string& dex_file_location(dex_cache->GetLocation()->ToModifiedUtf8());
-        const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file_location);
-        const DexFile* dex_file = oat_dex_file->OpenDexFile();
-        if (dex_file == NULL) {
-          LOG(FATAL) << "Failed to open dex file " << dex_file_location
-                     << " from within oat file " << oat_file->GetLocation();
-        }
-
-        CHECK_EQ(dex_file->GetLocationChecksum(), oat_dex_file->GetDexFileLocationChecksum());
-
-        AppendToBootClassPath(*dex_file, dex_cache);
-      }
+  CHECK_EQ(oat_file->GetOatHeader().GetDexFileCount(),
+           static_cast<uint32_t>(dex_caches->GetLength()));
+  for (int i = 0; i < dex_caches->GetLength(); i++) {
+    SirtRef<DexCache> dex_cache(dex_caches->Get(i));
+    const std::string& dex_file_location(dex_cache->GetLocation()->ToModifiedUtf8());
+    const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file_location);
+    const DexFile* dex_file = oat_dex_file->OpenDexFile();
+    if (dex_file == NULL) {
+      LOG(FATAL) << "Failed to open dex file " << dex_file_location
+                 << " from within oat file " << oat_file->GetLocation();
     }
+
+    CHECK_EQ(dex_file->GetLocationChecksum(), oat_dex_file->GetDexFileLocationChecksum());
+
+    AppendToBootClassPath(*dex_file, dex_cache);
   }
 
   HeapBitmap* heap_bitmap = heap->GetLiveBits();
@@ -919,7 +912,7 @@
 
   // reinit class_roots_
   Object* class_roots_object =
-      spaces[0]->AsImageSpace()->GetImageHeader().GetImageRoot(ImageHeader::kClassRoots);
+      heap->GetImageSpace()->GetImageHeader().GetImageRoot(ImageHeader::kClassRoots);
   class_roots_ = class_roots_object->AsObjectArray<Class>();
 
   // reinit array_iftable_ from any array class instance, they should be ==
diff --git a/src/dex2oat.cc b/src/dex2oat.cc
index debbabf..1f02a44 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -245,23 +245,6 @@
                        const std::set<std::string>* image_classes,
                        const std::string& oat_filename,
                        const std::string& oat_location) {
-    // If we have an existing boot image, position new space after its oat file
-    Heap* heap = Runtime::Current()->GetHeap();
-    if (heap->GetSpaces().size() > 1) {
-      ImageSpace* last_image_space = NULL;
-      const std::vector<Space*>& spaces = heap->GetSpaces();
-      for (size_t i=0; i < spaces.size(); i++) {
-        if (spaces[i]->IsImageSpace()) {
-          last_image_space = spaces[i]->AsImageSpace();
-        }
-      }
-      CHECK(last_image_space != NULL);
-      CHECK(last_image_space->IsImageSpace());
-      CHECK(!heap->GetSpaces()[heap->GetSpaces().size()-1]->IsImageSpace());
-      byte* oat_limit_addr = last_image_space->GetImageHeader().GetOatEnd();
-      image_base = RoundUp(reinterpret_cast<uintptr_t>(oat_limit_addr), kPageSize);
-    }
-
     ImageWriter image_writer(image_classes);
     if (!image_writer.Write(image_filename, image_base, oat_filename, oat_location)) {
       LOG(ERROR) << "Failed to create image file " << image_filename;
diff --git a/src/disassembler_arm.cc b/src/disassembler_arm.cc
index bbdc37e..e147c81 100644
--- a/src/disassembler_arm.cc
+++ b/src/disassembler_arm.cc
@@ -26,7 +26,6 @@
 DisassemblerArm::DisassemblerArm() {
 }
 
-
 void DisassemblerArm::Dump(std::ostream& os, const uint8_t* begin, const uint8_t* end) {
   if ((reinterpret_cast<intptr_t>(begin) & 1) == 0) {
     for (const uint8_t* cur = begin; cur < end; cur += 4) {
@@ -43,21 +42,22 @@
 }
 
 static const char* kConditionCodeNames[] = {
-    "EQ",  // 0000 - equal
-    "NE",  // 0001 - not-equal
-    "CS",  // 0010 - carry-set, greater than, equal or unordered
-    "CC",  // 0011 - carry-clear, less than
-    "MI",  // 0100 - minus, negative
-    "PL",  // 0101 - plus, positive or zero
-    "VS",  // 0110 - overflow
-    "VC",  // 0111 - no overflow
-    "HI",  // 1000 - unsigned higher
-    "LS",  // 1001 - unsigned lower or same
-    "GE",  // 1010 - signed greater than or equal
-    "LT",  // 1011 - signed less than
-    "GT",  // 1100 - signed greater than
-    "LE",  // 1101 - signed less than or equal
-    "",    // 1110 - always
+  "eq",  // 0000 - equal
+  "ne",  // 0001 - not-equal
+  "cs",  // 0010 - carry-set, greater than, equal or unordered
+  "cc",  // 0011 - carry-clear, less than
+  "mi",  // 0100 - minus, negative
+  "pl",  // 0101 - plus, positive or zero
+  "vs",  // 0110 - overflow
+  "vc",  // 0111 - no overflow
+  "hi",  // 1000 - unsigned higher
+  "ls",  // 1001 - unsigned lower or same
+  "ge",  // 1010 - signed greater than or equal
+  "lt",  // 1011 - signed less than
+  "gt",  // 1100 - signed greater than
+  "le",  // 1101 - signed less than or equal
+  "",    // 1110 - always
+  "nv",  // 1111 - never (mostly obsolete, but might be a clue that we're mistranslating)
 };
 
 void DisassemblerArm::DumpCond(std::ostream& os, uint32_t cond) {
@@ -70,10 +70,10 @@
 
 void DisassemblerArm::DumpReg(std::ostream& os, uint32_t reg) {
   switch (reg) {
-    case 13: os << "SP"; break;
-    case 14: os << "LR"; break;
-    case 15: os << "PC"; break;
-    default: os << "R" << reg; break;
+    case 13: os << "sp"; break;
+    case 14: os << "lr"; break;
+    case 15: os << "pc"; break;
+    default: os << "r" << reg; break;
   }
 }
 
@@ -90,8 +90,8 @@
 }
 
 static const char* kDataProcessingOperations[] = {
-  "AND", "EOR", "SUB", "RSB", "ADD", "ADC", "SBC", "RSC",
-  "TST", "TEQ", "CMP", "CMN", "ORR", "MOV", "BIC", "MVN",
+  "and", "eor", "sub", "rsb", "add", "adc", "sbc", "rsc",
+  "tst", "teq", "cmp", "cmn", "orr", "mov", "bic", "mvn",
 };
 
 struct ArmRegister {
@@ -100,13 +100,13 @@
 };
 std::ostream& operator<<(std::ostream& os, const ArmRegister& r) {
   if (r.r == 13) {
-    os << "SP";
+    os << "sp";
   } else if (r.r == 14) {
-    os << "LR";
+    os << "lr";
   } else if (r.r == 15) {
-    os << "PC";
+    os << "pc";
   } else {
-    os << "R" << r.r;
+    os << "r" << r.r;
   }
   return os;
 }
@@ -172,26 +172,27 @@
   uint32_t instruction = ReadU32(instr_ptr);
   uint32_t cond = (instruction >> 28) & 0xf;
   uint32_t op1 = (instruction >> 25) & 0x7;
-  os << StringPrintf("\t\t\t%p: %08x: ", instr_ptr, instruction);
+  std::ostringstream opcode;
+  std::ostringstream args;
   switch (op1) {
     case 0:
     case 1: // Data processing instructions.
       {
         if ((instruction & 0x0fffffd0) == 0x012fff10) { // BX and BLX (register)
-          os << (((instruction >> 5) & 1) ? "BLX" : "BX") << " " << ArmRegister(instruction & 0xf);
+          opcode << (((instruction >> 5) & 1) ? "blx" : "bx");
+          args << ArmRegister(instruction & 0xf);
           break;
         }
         bool i = (instruction & (1 << 25)) != 0;
         bool s = (instruction & (1 << 20)) != 0;
-        os << kDataProcessingOperations[(instruction >> 21) & 0xf]
-           << kConditionCodeNames[cond]
-           << (s ? "S" : "")
-           << " "
-           << Rd(instruction) << ", ";
+        opcode << kDataProcessingOperations[(instruction >> 21) & 0xf]
+               << kConditionCodeNames[cond]
+               << (s ? "s" : "");
+        args << Rd(instruction) << ", ";
         if (i) {
-          os << Rn(instruction) << ", " << Imm12(instruction);
+          args << Rn(instruction) << ", " << Imm12(instruction);
         } else {
-          os << Rm(instruction);
+          args << Rm(instruction);
         }
       }
       break;
@@ -201,18 +202,18 @@
         bool b = (instruction & (1 << 22)) != 0;
         bool w = (instruction & (1 << 21)) != 0;
         bool l = (instruction & (1 << 20)) != 0;
-        os << (l ? "LDR" : "STR") << (b ? "B" : "") << kConditionCodeNames[cond] << " ";
-        os << Rt(instruction) << ", ";
+        opcode << (l ? "ldr" : "str") << (b ? "b" : "") << kConditionCodeNames[cond];
+        args << Rt(instruction) << ", ";
         if (Rn(instruction).r == 0xf) {
           UNIMPLEMENTED(FATAL) << "literals";
         } else {
           bool wback = !p || w;
           if (p && !wback) {
-            os << "[" << Rn(instruction) << ", " << Imm12(instruction) << "]";
+            args << "[" << Rn(instruction) << ", " << Imm12(instruction) << "]";
           } else if (p && wback) {
-            os << "[" << Rn(instruction) << ", " << Imm12(instruction) << "]!";
+            args << "[" << Rn(instruction) << ", " << Imm12(instruction) << "]!";
           } else if (!p && wback) {
-            os << "[" << Rn(instruction) << "], " << Imm12(instruction);
+            args << "[" << Rn(instruction) << "], " << Imm12(instruction);
           } else {
             LOG(FATAL) << p << " " << w;
           }
@@ -225,19 +226,19 @@
         bool u = (instruction & (1 << 23)) != 0;
         bool w = (instruction & (1 << 21)) != 0;
         bool l = (instruction & (1 << 20)) != 0;
-        os << StringPrintf("%s%c%c%s ",
-                           l ? "LDM" : "STM",
-                           u ? 'I' : 'D',
-                           p ? 'B' : 'A',
-                           kConditionCodeNames[cond]);
-        os << Rn(instruction) << (w ? "!" : "") << ", " << RegisterList(instruction);
+        opcode << (l ? "ldm" : "stm")
+               << (u ? 'i' : 'd')
+               << (p ? 'b' : 'a')
+               << kConditionCodeNames[cond];
+        args << Rn(instruction) << (w ? "!" : "") << ", " << RegisterList(instruction);
       }
       break;
     default:
-      os << "???";
+      opcode << "???";
       break;
     }
-    os << '\n';
+    // TODO: a more complete ARM disassembler could generate wider opcodes.
+    os << StringPrintf("\t\t\t%p: %08x\t%-7s ", instr_ptr, instruction, opcode.str().c_str()) << args.str() << '\n';
 }
 
 size_t DisassemblerArm::DumpThumb32(std::ostream& os, const uint8_t* instr_ptr) {
@@ -255,7 +256,8 @@
   }
 
   uint32_t op2 = (instr >> 20) & 0x7F;
-  os << StringPrintf("\t\t\t%p: %08x: ", instr_ptr, instr);
+  std::ostringstream opcode;
+  std::ostringstream args;
   switch (op1) {
     case 0:
       break;
@@ -282,50 +284,50 @@
           if (op == 1 || op == 2) {
             if (op == 1) {
               if (L == 0) {
-                os << "STM ";
-                DumpReg(os, Rn);
+                opcode << "stm";
+                DumpReg(args, Rn);
                 if (W == 0) {
-                  os << ", ";
+                  args << ", ";
                 } else {
-                  os << "!, ";
+                  args << "!, ";
                 }
               } else {
                 if (Rn != 13) {
-                  os << "LDM ";
-                  DumpReg(os, Rn);
+                  opcode << "ldm";
+                  DumpReg(args, Rn);
                   if (W == 0) {
-                    os << ", ";
+                    args << ", ";
                   } else {
-                    os << "!, ";
+                    args << "!, ";
                   }
                 } else {
-                  os << "POP ";
+                  opcode << "pop";
                 }
               }
             } else {
               if (L == 0) {
                 if (Rn != 13) {
-                  os << "STMDB ";
-                  DumpReg(os, Rn);
+                  opcode << "stmdb";
+                  DumpReg(args, Rn);
                   if (W == 0) {
-                    os << ", ";
+                    args << ", ";
                   } else {
-                    os << "!, ";
+                    args << "!, ";
                   }
                 } else {
-                  os << "PUSH ";
+                  opcode << "push";
                 }
               } else {
-                os << "LDMDB ";
-                DumpReg(os, Rn);
+                opcode << "ldmdb";
+                DumpReg(args, Rn);
                 if (W == 0) {
-                  os << ", ";
+                  args << ", ";
                 } else {
-                  os << "!, ";
+                  args << "!, ";
                 }
               }
             }
-            os << RegisterList(instr);
+            args << RegisterList(instr);
           }
           break;
         }
@@ -354,27 +356,25 @@
         uint32_t imm8 = instr & 0xFF;
         int32_t imm32 = (i << 12) | (imm3 << 8) | imm8;
         switch (op3) {
-          case 0x0: os << "AND"; break;
-          case 0x1: os << "BIC"; break;
-          case 0x2: os << "ORR"; break;
-          case 0x3: os << "ORN"; break;
-          case 0x4: os << "EOR"; break;
-          case 0x8: os << "ADD"; break;
-          case 0xA: os << "ADC"; break;
-          case 0xB: os << "SBC"; break;
-          case 0xD: os << "SUB"; break;
-          case 0xE: os << "RSB"; break;
-          default: os << "UNKNOWN DPMI-" << op3; break;
+          case 0x0: opcode << "and"; break;
+          case 0x1: opcode << "bic"; break;
+          case 0x2: opcode << "orr"; break;
+          case 0x3: opcode << "orn"; break;
+          case 0x4: opcode << "eor"; break;
+          case 0x8: opcode << "add"; break;
+          case 0xA: opcode << "adc"; break;
+          case 0xB: opcode << "sbc"; break;
+          case 0xD: opcode << "sub"; break;
+          case 0xE: opcode << "rsb"; break;
+          default: opcode << "UNKNOWN DPMI-" << op3; break;
         }
         if (S == 1) {
-          os << "S ";
-        } else {
-          os << " ";
+          opcode << "s";
         }
-        DumpReg(os, Rd);
-        os << ", ";
-        DumpReg(os, Rn);
-        os << ", ThumbExpand(" << imm32 << ")";
+        DumpReg(args, Rd);
+        args << ", ";
+        DumpReg(args, Rn);
+        args << ", ThumbExpand(" << imm32 << ")";
       } else if ((instr & 0x8000) == 0 && (op2 & 0x20) != 0) {
         // Data-processing (plain binary immediate)
         // |111|11|10|00000|0000|1|111110000000000|
@@ -394,9 +394,9 @@
             uint32_t imm3 = (instr >> 12) & 0x7;
             uint32_t imm8 = instr & 0xFF;
             uint32_t imm16 = (Rn << 12) | (i << 11) | (imm3 << 8) | imm8;
-            os << "MOVW ";
-            DumpReg(os, Rd);
-            os << ", #" << imm16;
+            opcode << "movw";
+            DumpReg(args, Rd);
+            args << ", #" << imm16;
             break;
           }
           case 0x0A: {
@@ -406,11 +406,11 @@
             uint32_t imm3 = (instr >> 12) & 0x7;
             uint32_t imm8 = instr & 0xFF;
             uint32_t imm12 = (i << 11) | (imm3 << 8) | imm8;
-            os << "SUB.W ";
-            DumpReg(os, Rd);
-            os << ", ";
-            DumpReg(os, Rn);
-            os << ", #" << imm12;
+            opcode << "sub.w";
+            DumpReg(args, Rd);
+            args << ", ";
+            DumpReg(args, Rn);
+            args << ", #" << imm12;
             break;
           }
           default:
@@ -447,10 +447,10 @@
               uint32_t cond = (instr >> 22) & 0xF;
               int32_t imm32 = (S << 20) |  (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
               imm32 = (imm32 << 11) >> 11;  // sign extend 21bit immediate
-              os << "B";
-              DumpCond(os, cond);
-              os << ".W ";
-              DumpBranchTarget(os, instr_ptr + 4, imm32);
+              opcode << "b";
+              DumpCond(opcode, cond);
+              opcode << ".w";
+              DumpBranchTarget(args, instr_ptr + 4, imm32);
             }
             break;
           case 2:
@@ -472,15 +472,15 @@
             uint32_t imm10 = (instr >> 16) & 0x3FF;
             uint32_t imm11 = instr & 0x7FF;
             if (L == 0) {
-              os << "BX ";
+              opcode << "bx";
             } else {
-              os << "BLX ";
+              opcode << "blx";
             }
             uint32_t I1 = ~(J1 ^ S);
             uint32_t I2 = ~(J2 ^ S);
             int32_t imm32 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
             imm32 = (imm32 << 8) >> 8;  // sign extend 24 bit immediate.
-            DumpBranchTarget(os, instr_ptr + 4, imm32);
+            DumpBranchTarget(args, instr_ptr + 4, imm32);
             break;
           }
         }
@@ -514,35 +514,35 @@
                 uint32_t imm8 = instr & 0xFF;
                 int32_t imm32 = (imm8 << 24) >> 24;  // sign-extend imm8
                 if (Rn == 13 && P == 1 && U == 0 && W == 1) {
-                  os << "PUSH ";
-                  DumpReg(os, Rt);
+                  opcode << "push";
+                  DumpReg(args, Rt);
                 } else if (Rn == 15 || (P == 0 && W == 0)) {
-                  os << "UNDEFINED ";
+                  opcode << "UNDEFINED";
                 } else {
                   if (P == 1 && U == 1 && W == 0) {
-                    os << "STRT ";
+                    opcode << "strt";
                   } else {
-                    os << "STR ";
+                    opcode << "str";
                   }
-                  DumpReg(os, Rt);
-                  os << ", [";
-                  DumpReg(os, Rn);
+                  DumpReg(args, Rt);
+                  args << ", [";
+                  DumpReg(args, Rn);
                   if (P == 0 && W == 1) {
-                    os << "], #" << imm32;
+                    args << "], #" << imm32;
                   } else {
-                    os << ", #" << imm32 << "]";
+                    args << ", #" << imm32 << "]";
                     if (W == 1) {
-                      os << "!";
+                      args << "!";
                     }
                   }
                 }
               } else if (op3 == 6) {
                 uint32_t imm12 = instr & 0xFFF;
-                os << "STR.W ";
-                DumpReg(os, Rt);
-                os << ", [";
-                DumpReg(os, Rn);
-                os << ", #" << imm12 << "]";
+                opcode << "str.w";
+                DumpReg(args, Rt);
+                args << ", [";
+                DumpReg(args, Rn);
+                args << ", #" << imm12 << "]";
               }
               break;
             }
@@ -568,33 +568,33 @@
             // LDR.W Rt, [Rn, #imm12]          - 111 11 00 00 101 nnnn tttt iiiiiiiiiiii
             // LDR.W Rt, [PC, #imm12]          - 111 11 00 0x 101 1111 tttt iiiiiiiiiiii
             uint32_t imm12 = instr & 0xFFF;
-            os << "LDR.W ";
-            DumpReg(os, Rt);
-            os << ", [";
-            DumpReg(os, Rn);
-            os << ", #" << imm12 << "]";
+            opcode << "ldr.w";
+            DumpReg(args, Rt);
+            args << ", [";
+            DumpReg(args, Rn);
+            args << ", #" << imm12 << "]";
           } else if (op4 == 0) {
             // LDR.W Rt, [Rn, Rm{, LSL #imm2}] - 111 11 00 00 101 nnnn tttt 000000iimmmm
             uint32_t imm2 = (instr >> 4) & 0xF;
             uint32_t rm = instr & 0xF;
-            os << "LDR.W ";
-            DumpReg(os, Rt);
-            os << ", [";
-            DumpReg(os, Rn);
-            os << ", ";
-            DumpReg(os, rm);
+            opcode << "ldr.w";
+            DumpReg(args, Rt);
+            args << ", [";
+            DumpReg(args, Rn);
+            args << ", ";
+            DumpReg(args, rm);
             if (imm2 != 0) {
-              os << ", LSL #" << imm2;
+              args << ", lsl #" << imm2;
             }
-            os << "]";
+            args << "]";
           } else {
             // LDRT Rt, [Rn, #imm8]            - 111 11 00 00 101 nnnn tttt 1110iiiiiiii
             uint32_t imm8 = instr & 0xFF;
-            os << "LDRT ";
-            DumpReg(os, Rt);
-            os << ", [";
-            DumpReg(os, Rn);
-            os << ", #" << imm8 << "]";
+            opcode << "ldrt";
+            DumpReg(args, Rt);
+            args << ", [";
+            DumpReg(args, Rn);
+            args << ", #" << imm8 << "]";
           }
           break;
         }
@@ -602,7 +602,7 @@
     default:
       break;
   }
-  os << '\n';
+  os << StringPrintf("\t\t\t%p: %08x\t%-7s ", instr_ptr, instr, opcode.str().c_str()) << args.str() << '\n';
   return 4;
 }
 
@@ -612,7 +612,8 @@
   if (is_32bit) {
     return DumpThumb32(os, instr_ptr);
   } else {
-    os << StringPrintf("\t\t\t%p: %04x    : ", instr_ptr, instr);
+    std::ostringstream opcode;
+    std::ostringstream args;
     uint16_t opcode1 = instr >> 10;
     if (opcode1 < 0x10) {
       // shift (immediate), add, subtract, move, and compare
@@ -627,16 +628,16 @@
           uint16_t rm = (instr >> 3) & 7;
           uint16_t Rd = instr & 7;
           if (opcode2 <= 3) {
-            os << "LSLS ";
+            opcode << "lsls";
           } else if (opcode2 <= 7) {
-            os << "LSRS ";
+            opcode << "lsrs";
           } else {
-            os << "ASRS ";
+            opcode << "asrs";
           }
-          DumpReg(os, Rd);
-          os << ", ";
-          DumpReg(os, rm);
-          os << ", #" << imm5;
+          DumpReg(args, Rd);
+          args << ", ";
+          DumpReg(args, rm);
+          args << ", #" << imm5;
           break;
         }
         case 0xC: case 0xD: case 0xE: case 0xF: {
@@ -648,22 +649,22 @@
           uint16_t Rn = (instr >> 3) & 7;
           uint16_t Rd = instr & 7;
           if ((opcode2 & 2) != 0 && imm3_or_Rm == 0) {
-            os << "MOV ";
+            opcode << "mov";
           } else {
             if ((opcode2 & 1) == 0) {
-              os << "ADDS ";
+              opcode << "adds";
             } else {
-              os << "SUBS ";
+              opcode << "subs";
             }
           }
-          DumpReg(os, Rd);
-          os << ", ";
-          DumpReg(os, Rn);
+          DumpReg(args, Rd);
+          args << ", ";
+          DumpReg(args, Rn);
           if ((opcode2 & 2) == 0) {
-            os << ", ";
-            DumpReg(os, imm3_or_Rm);
+            args << ", ";
+            DumpReg(args, imm3_or_Rm);
           } else if (imm3_or_Rm != 0) {
-            os << ", #" << imm3_or_Rm;
+            args << ", #" << imm3_or_Rm;
           }
           break;
         }
@@ -678,13 +679,13 @@
           uint16_t Rn = (instr >> 8) & 7;
           uint16_t imm8 = instr & 0xFF;
           switch (opcode2 >> 2) {
-            case 4: os << "MOVS "; break;
-            case 5: os << "CMP "; break;
-            case 6: os << "ADDS "; break;
-            case 7: os << "SUBS "; break;
+            case 4: opcode << "movs"; break;
+            case 5: opcode << "cmp"; break;
+            case 6: opcode << "adds"; break;
+            case 7: opcode << "subs"; break;
           }
-          DumpReg(os, Rn);
-          os << ", #" << imm8;
+          DumpReg(args, Rn);
+          args << ", #" << imm8;
           break;
         }
         default:
@@ -701,10 +702,10 @@
           uint16_t rm = (instr >> 3) & 0xF;
           uint16_t Rdn = instr & 7;
           uint16_t DN_Rdn = (DN << 3) | Rdn;
-          os << "ADD ";
-          DumpReg(os, DN_Rdn);
-          os << ", ";
-          DumpReg(os, rm);
+          opcode << "add";
+          DumpReg(args, DN_Rdn);
+          args << ", ";
+          DumpReg(args, rm);
           break;
         }
         case 0x8: case 0x9: case 0xA: case 0xB: {
@@ -714,10 +715,10 @@
           uint16_t rm = (instr >> 3) & 0xF;
           uint16_t Rdn = instr & 7;
           uint16_t DN_Rdn = (DN << 3) | Rdn;
-          os << "MOV ";
-          DumpReg(os, DN_Rdn);
-          os << ", ";
-          DumpReg(os, rm);
+          opcode << "mov";
+          DumpReg(args, DN_Rdn);
+          args << ", ";
+          DumpReg(args, rm);
           break;
         }
         case 0x5: case 0x6: case 0x7: {
@@ -726,10 +727,10 @@
           uint16_t rm = (instr >> 3) & 0xF;
           uint16_t Rn = instr & 7;
           uint16_t N_Rn = (N << 3) | Rn;
-          os << "CMP ";
-          DumpReg(os, N_Rn);
-          os << ", ";
-          DumpReg(os, rm);
+          opcode << "cmp";
+          DumpReg(args, N_Rn);
+          args << ", ";
+          DumpReg(args, rm);
           break;
         }
         case 0xC: case 0xD: case 0xE: case 0xF: {
@@ -737,11 +738,11 @@
           // Branch with link and exchange - 010001 111x xxxxxx
           uint16_t rm = instr >> 3 & 0xF;
           if ((opcode2 & 0x2) == 0) {
-            os << "BX ";
+            opcode << "bx";
           } else {
-            os << "BLX ";
+            opcode << "blx";
           }
-          DumpReg(os, rm);
+          DumpReg(args, rm);
           break;
         }
         default:
@@ -756,11 +757,11 @@
           // Subtract immediate from SP - 1011 00001 ii iiiii
           int imm7 = instr & 0x7F;
           if ((opcode2 & 4) == 0) {
-            os << "ADD SP, SP, #";
+            opcode << "add";
           } else {
-            os << "SUB SP, SP, #";
+            opcode << "sub";
           }
-          os << (imm7 << 2);
+          args << "sp, sp, #" << (imm7 << 2);
           break;
         }
         case 0x78: case 0x79: case 0x7A: case 0x7B:  // 1111xxx
@@ -770,15 +771,16 @@
           uint16_t opB = instr & 0xF;
           if (opB == 0) {
             switch (opA) {
-              case 0: os << "NOP  // "; break;
-              case 1: os << "YIELD  // "; break;
-              case 2: os << "WFE  // ";  break;
-              case 3: os << "SEV  // "; break;
+              case 0: opcode << "nop"; break;
+              case 1: opcode << "yield"; break;
+              case 2: opcode << "wfe";  break;
+              case 3: opcode << "sev"; break;
               default: break;
             }
           } else {
-            os << "IT " << reinterpret_cast<void*>(opB) << " ";
-            DumpCond(os, opA);
+            opcode << "it";
+            args << reinterpret_cast<void*>(opB) << " ";
+            DumpCond(args, opA);
           }
           break;
         }
@@ -798,14 +800,14 @@
           uint16_t Rn = (instr >> 3) & 7;
           uint16_t Rt = instr & 7;
           if ((instr & 0x800) == 0) {
-            os << "STR ";
+            opcode << "str";
           } else {
-            os << "LDR ";
+            opcode << "ldr";
           }
-          DumpReg(os, Rt);
-          os << ", [";
-          DumpReg(os, Rn);
-          os << ", #" << (imm5 << 2) << "]";
+          DumpReg(args, Rt);
+          args << ", [";
+          DumpReg(args, Rn);
+          args << ", #" << (imm5 << 2) << "]";
           break;
         }
         case 0x9: {
@@ -814,12 +816,12 @@
           uint16_t imm8 = instr & 0xFF;
           uint16_t Rt = (instr >> 8) & 7;
           if ((instr & 0x800) == 0) {
-            os << "STR ";
+            opcode << "str";
           } else {
-            os << "LDR ";
+            opcode << "ldr";
           }
-          DumpReg(os, Rt);
-          os << ", [SP, #" << (imm8 << 2) << "]";
+          DumpReg(args, Rt);
+          args << ", [sp, #" << (imm8 << 2) << "]";
           break;
         }
         default:
@@ -829,10 +831,10 @@
       uint16_t imm11 = instr & 0x7FFF;
       int32_t imm32 = imm11 << 1;
       imm32 = (imm32 << 20) >> 20;  // sign extend 12 bit immediate
-      os << "B ";
-      DumpBranchTarget(os, instr_ptr + 4, imm32);
+      opcode << "b";
+      DumpBranchTarget(args, instr_ptr + 4, imm32);
     }
-    os << '\n';
+    os << StringPrintf("\t\t\t%p: %04x    \t%-7s ", instr_ptr, instr, opcode.str().c_str()) << args.str() << '\n';
   }
   return 2;
 }
diff --git a/src/heap.cc b/src/heap.cc
index f4f2996..189bb91 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -132,6 +132,7 @@
 Heap::Heap(size_t initial_size, size_t growth_limit, size_t capacity,
            const std::string& original_image_file_name)
     : lock_(NULL),
+      image_space_(NULL),
       alloc_space_(NULL),
       mark_bitmap_(NULL),
       live_bitmap_(NULL),
@@ -163,35 +164,34 @@
   byte* requested_begin = NULL;
   std::string image_file_name(original_image_file_name);
   if (!image_file_name.empty()) {
-    ImageSpace* space = NULL;
     if (OS::FileExists(image_file_name.c_str())) {
       // If the /system file exists, it should be up-to-date, don't try to generate
-      space = Space::CreateImageSpace(image_file_name);
+      image_space_ = Space::CreateImageSpace(image_file_name);
     } else {
       // If the /system file didn't exist, we need to use one from the art-cache.
       // If the cache file exists, try to open, but if it fails, regenerate.
       // If it does not exist, generate.
       image_file_name = GetArtCacheFilenameOrDie(image_file_name);
       if (OS::FileExists(image_file_name.c_str())) {
-        space = Space::CreateImageSpace(image_file_name);
+        image_space_ = Space::CreateImageSpace(image_file_name);
       }
-      if (space == NULL) {
+      if (image_space_ == NULL) {
         if (!GenerateImage(image_file_name)) {
           LOG(FATAL) << "Failed to generate image: " << image_file_name;
         }
-        space = Space::CreateImageSpace(image_file_name);
+        image_space_ = Space::CreateImageSpace(image_file_name);
       }
     }
-    if (space == NULL) {
+    if (image_space_ == NULL) {
       LOG(FATAL) << "Failed to create space from " << image_file_name;
     }
 
-    AddSpace(space);
-    UpdateFirstAndLastSpace(&first_space, &last_space, space);
+    AddSpace(image_space_);
+    UpdateFirstAndLastSpace(&first_space, &last_space, image_space_);
     // Oat files referenced by image files immediately follow them in memory, ensure alloc space
     // isn't going to get in the middle
-    byte* oat_end_addr = space->GetImageHeader().GetOatEnd();
-    CHECK(oat_end_addr > space->End());
+    byte* oat_end_addr = image_space_->GetImageHeader().GetOatEnd();
+    CHECK(oat_end_addr > image_space_->End());
     if (oat_end_addr > requested_begin) {
       requested_begin = reinterpret_cast<byte*>(RoundUp(reinterpret_cast<uintptr_t>(oat_end_addr),
                                                         kPageSize));
diff --git a/src/heap.h b/src/heap.h
index ccc2d23..374fa84 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -33,6 +33,7 @@
 
 class AllocSpace;
 class Class;
+class ImageSpace;
 class Object;
 class Space;
 class Thread;
@@ -208,7 +209,13 @@
   size_t GetBytesAllocated() { return num_bytes_allocated_; }
   size_t GetObjectsAllocated() { return num_objects_allocated_; }
 
+  ImageSpace* GetImageSpace() {
+    CHECK(image_space_ != NULL);
+    return image_space_;
+  }
+
   AllocSpace* GetAllocSpace() {
+    CHECK(alloc_space_ != NULL);
     return alloc_space_;
   }
 
@@ -242,6 +249,8 @@
 
   std::vector<Space*> spaces_;
 
+  ImageSpace* image_space_;
+
   // default Space for allocations
   AllocSpace* alloc_space_;
 
diff --git a/src/image_test.cc b/src/image_test.cc
index e886e49..fcea695 100644
--- a/src/image_test.cc
+++ b/src/image_test.cc
@@ -64,6 +64,7 @@
     Space* space = heap->GetSpaces()[0];
     ASSERT_FALSE(space->IsImageSpace());
     ASSERT_TRUE(space != NULL);
+    ASSERT_EQ(space, heap->GetAllocSpace());
     ASSERT_GE(sizeof(image_header) + space->Size(), static_cast<size_t>(file->Length()));
   }
 
@@ -88,9 +89,13 @@
   Heap* heap = Runtime::Current()->GetHeap();
   ASSERT_EQ(2U, heap->GetSpaces().size());
   ASSERT_TRUE(heap->GetSpaces()[0]->IsImageSpace());
+  ASSERT_FALSE(heap->GetSpaces()[0]->IsAllocSpace());
   ASSERT_FALSE(heap->GetSpaces()[1]->IsImageSpace());
+  ASSERT_TRUE(heap->GetSpaces()[1]->IsAllocSpace());
+  ASSERT_TRUE(heap->GetImageSpace() != NULL);
+  ASSERT_TRUE(heap->GetAllocSpace() != NULL);
 
-  ImageSpace* image_space = heap->GetSpaces()[0]->AsImageSpace();
+  ImageSpace* image_space = heap->GetImageSpace();
   byte* image_begin = image_space->Begin();
   byte* image_end = image_space->End();
   CHECK_EQ(requested_image_base, reinterpret_cast<uintptr_t>(image_begin));
diff --git a/src/image_writer.cc b/src/image_writer.cc
index 4579c0c..cc37e5b 100644
--- a/src/image_writer.cc
+++ b/src/image_writer.cc
@@ -49,11 +49,7 @@
   image_begin_ = reinterpret_cast<byte*>(image_begin);
 
   Heap* heap = Runtime::Current()->GetHeap();
-  const std::vector<Space*>& spaces = heap->GetSpaces();
-  // currently just write the last space, assuming it is the space that was being used for allocation
-  CHECK_GE(spaces.size(), 1U);
-  source_space_ = spaces[spaces.size()-1];
-  CHECK(!source_space_->IsImageSpace());
+  source_space_ = heap->GetAllocSpace();
 
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   const std::vector<DexCache*>& all_dex_caches = class_linker->GetDexCaches();
diff --git a/src/oatdump.cc b/src/oatdump.cc
index 9641390..295c74f 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -1154,7 +1154,7 @@
   }
 
   Heap* heap = Runtime::Current()->GetHeap();
-  ImageSpace* image_space = heap->GetSpaces()[heap->GetSpaces().size()-2]->AsImageSpace();
+  ImageSpace* image_space = heap->GetImageSpace();
   CHECK(image_space != NULL);
   const ImageHeader& image_header = image_space->GetImageHeader();
   if (!image_header.IsValid()) {