Merge "Fix for Mac build." into dalvik-dev
diff --git a/Android.mk b/Android.mk
index 097dd08..3e17072 100644
--- a/Android.mk
+++ b/Android.mk
@@ -274,7 +274,7 @@
 # oatdump targets
 
 .PHONY: dump-oat
-dump-oat: dump-oat-core dump-oat-boot
+dump-oat: dump-oat-core dump-oat-boot dump-oat-Calculator
 
 .PHONY: dump-oat-core
 dump-oat-core: dump-oat-core-host dump-oat-core-target
@@ -294,6 +294,12 @@
 	$(OATDUMP) --image=$(TARGET_BOOT_IMG_OUT) --output=/tmp/boot.oatdump.txt
 	@echo Output in /tmp/boot.oatdump.txt
 
+.PHONY: dump-oat-Calculator
+dump-oat-Calculator: $(TARGET_OUT_APPS)/Calculator.apk.oat $(TARGET_BOOT_IMG_OUT) $(OATDUMP)
+	$(OATDUMP) --oat-file=$< --output=/tmp/Calculator.oatdump.txt
+	@echo Output in /tmp/Calculator.oatdump.txt
+
+
 ########################################################################
 # cpplint target
 
diff --git a/build/Android.common.mk b/build/Android.common.mk
index 0373b58..5d89c40 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -373,6 +373,7 @@
 
 
 LIBART_ENUM_OPERATOR_OUT_HEADER_FILES := \
+	src/dex_file.h \
 	src/dex_instruction.h \
 	src/gc/space.h \
 	src/heap.h \
diff --git a/build/Android.libart.mk b/build/Android.libart.mk
index 6eaa778..43ce31a 100644
--- a/build/Android.libart.mk
+++ b/build/Android.libart.mk
@@ -104,7 +104,7 @@
   LOCAL_SHARED_LIBRARIES := liblog libnativehelper
   LOCAL_SHARED_LIBRARIES += libcorkscrew # native stack trace support
   ifeq ($$(art_target_or_host),target)
-    LOCAL_SHARED_LIBRARIES += libcutils libstlport libz libdl
+    LOCAL_SHARED_LIBRARIES += libcutils libstlport libz libdl libselinux
     LOCAL_SHARED_LIBRARIES += libdynamic_annotations # tsan support
   else # host
     LOCAL_STATIC_LIBRARIES += libcutils
diff --git a/src/check_jni.cc b/src/check_jni.cc
index e7590d3..7c5186a 100644
--- a/src/check_jni.cc
+++ b/src/check_jni.cc
@@ -208,6 +208,7 @@
         // obj will be NULL.  Otherwise, obj should always be non-NULL
         // and valid.
         if (!Runtime::Current()->GetHeap()->IsHeapAddress(obj)) {
+          Runtime::Current()->GetHeap()->DumpSpaces();
           JniAbortF(function_name_, "field operation on invalid %s: %p",
                     ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object);
           return;
@@ -244,6 +245,7 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     Object* o = soa_.Decode<Object*>(java_object);
     if (o == NULL || !Runtime::Current()->GetHeap()->IsHeapAddress(o)) {
+      Runtime::Current()->GetHeap()->DumpSpaces();
       JniAbortF(function_name_, "field operation on invalid %s: %p",
                 ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object);
       return;
@@ -623,6 +625,7 @@
 
     Object* obj = soa_.Decode<Object*>(java_object);
     if (!Runtime::Current()->GetHeap()->IsHeapAddress(obj)) {
+      Runtime::Current()->GetHeap()->DumpSpaces();
       JniAbortF(function_name_, "%s is an invalid %s: %p (%p)",
                 what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object, obj);
       return false;
@@ -676,6 +679,7 @@
 
     Array* a = soa_.Decode<Array*>(java_array);
     if (!Runtime::Current()->GetHeap()->IsHeapAddress(a)) {
+      Runtime::Current()->GetHeap()->DumpSpaces();
       JniAbortF(function_name_, "jarray is an invalid %s: %p (%p)",
                 ToStr<IndirectRefKind>(GetIndirectRefKind(java_array)).c_str(), java_array, a);
     } else if (!a->IsArrayInstance()) {
@@ -696,6 +700,7 @@
     }
     Field* f = soa_.DecodeField(fid);
     if (!Runtime::Current()->GetHeap()->IsHeapAddress(f) || !f->IsField()) {
+      Runtime::Current()->GetHeap()->DumpSpaces();
       JniAbortF(function_name_, "invalid jfieldID: %p", fid);
       return NULL;
     }
@@ -709,6 +714,7 @@
     }
     AbstractMethod* m = soa_.DecodeMethod(mid);
     if (!Runtime::Current()->GetHeap()->IsHeapAddress(m) || !m->IsMethod()) {
+      Runtime::Current()->GetHeap()->DumpSpaces();
       JniAbortF(function_name_, "invalid jmethodID: %p", mid);
       return NULL;
     }
@@ -729,6 +735,7 @@
 
     Object* o = soa_.Decode<Object*>(java_object);
     if (!Runtime::Current()->GetHeap()->IsHeapAddress(o)) {
+      Runtime::Current()->GetHeap()->DumpSpaces();
       // TODO: when we remove work_around_app_jni_bugs, this should be impossible.
       JniAbortF(function_name_, "native code passing in reference to invalid %s: %p",
                 ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object);
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 83661cb..a76c9c8 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -222,6 +222,7 @@
       class_roots_(NULL),
       array_iftable_(NULL),
       init_done_(false),
+      is_dirty_(false),
       intern_table_(intern_table) {
   CHECK_EQ(arraysize(class_roots_descriptors_), size_t(kClassRootsMax));
 }
@@ -706,7 +707,7 @@
   uint32_t image_oat_checksum = image_header.GetOatChecksum();
   if (oat_checksum != image_oat_checksum) {
     LOG(ERROR) << "Failed to match oat file checksum " << std::hex << oat_checksum
-               << " to expected oat checksum " << std::hex << oat_checksum
+               << " to expected oat checksum " << std::hex << image_oat_checksum
                << " in image";
     return NULL;
   }
@@ -742,7 +743,11 @@
   }
   Runtime* runtime = Runtime::Current();
   const ImageHeader& image_header = runtime->GetHeap()->GetImageSpace()->GetImageHeader();
-  if (oat_file->GetOatHeader().GetImageFileLocationChecksum() != image_header.GetOatChecksum()) {
+  if (oat_file->GetOatHeader().GetImageFileLocationOatChecksum() != image_header.GetOatChecksum()) {
+    return NULL;
+  }
+  if (oat_file->GetOatHeader().GetImageFileLocationOatBegin()
+      != reinterpret_cast<uint32_t>(image_header.GetOatBegin())) {
     return NULL;
   }
   const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_location);
@@ -813,8 +818,10 @@
                                          uint32_t dex_location_checksum) {
   Runtime* runtime = Runtime::Current();
   const ImageHeader& image_header = runtime->GetHeap()->GetImageSpace()->GetImageHeader();
-  uint32_t image_checksum = image_header.GetOatChecksum();
-  bool image_check = (oat_file->GetOatHeader().GetImageFileLocationChecksum() == image_checksum);
+  uint32_t image_oat_checksum = image_header.GetOatChecksum();
+  uint32_t image_oat_begin = reinterpret_cast<uint32_t>(image_header.GetOatBegin());
+  bool image_check = ((oat_file->GetOatHeader().GetImageFileLocationOatChecksum() == image_oat_checksum)
+                      && (oat_file->GetOatHeader().GetImageFileLocationOatBegin() == image_oat_begin));
 
   const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_location);
   if (oat_dex_file == NULL) {
@@ -828,7 +835,7 @@
     }
     return false;
   }
-  bool dex_check = (dex_location_checksum == oat_dex_file->GetDexFileLocationChecksum());
+  bool dex_check = dex_location_checksum == oat_dex_file->GetDexFileLocationChecksum();
 
   if (image_check && dex_check) {
     return true;
@@ -838,14 +845,15 @@
     std::string image_file(image_header.GetImageRoot(
         ImageHeader::kOatLocation)->AsString()->ToModifiedUtf8());
     LOG(WARNING) << ".oat file " << oat_file->GetLocation()
-                 << " checksum ( " << std::hex << oat_dex_file->GetDexFileLocationChecksum()
-                 << ") mismatch with " << image_file
-                 << " (" << std::hex << image_checksum << ")";
+                 << " mismatch ( " << std::hex << oat_file->GetOatHeader().GetImageFileLocationOatChecksum()
+                 << ", " << oat_file->GetOatHeader().GetImageFileLocationOatBegin()
+                 << ") with " << image_file
+                 << " (" << image_oat_checksum << ", " << std::hex << image_oat_begin << ")";
   }
   if (!dex_check) {
     LOG(WARNING) << ".oat file " << oat_file->GetLocation()
-                 << " checksum ( " << std::hex << oat_dex_file->GetDexFileLocationChecksum()
-                 << ") mismatch with " << dex_location
+                 << " mismatch ( " << std::hex << oat_dex_file->GetDexFileLocationChecksum()
+                 << ") with " << dex_location
                  << " (" << std::hex << dex_location_checksum << ")";
   }
   return false;
@@ -957,7 +965,8 @@
   ImageSpace* space = heap->GetImageSpace();
   OatFile* oat_file = OpenOat(space);
   CHECK(oat_file != NULL) << "Failed to open oat file for image";
-  CHECK_EQ(oat_file->GetOatHeader().GetImageFileLocationChecksum(), 0U);
+  CHECK_EQ(oat_file->GetOatHeader().GetImageFileLocationOatChecksum(), 0U);
+  CHECK_EQ(oat_file->GetOatHeader().GetImageFileLocationOatBegin(), 0U);
   CHECK(oat_file->GetOatHeader().GetImageFileLocation().empty());
   Object* dex_caches_object = space->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches);
   ObjectArray<DexCache>* dex_caches = dex_caches_object->AsObjectArray<DexCache>();
@@ -1043,7 +1052,7 @@
 // Keep in sync with InitCallback. Anything we visit, we need to
 // reinit references to when reinitializing a ClassLinker from a
 // mapped image.
-void ClassLinker::VisitRoots(Heap::RootVisitor* visitor, void* arg) const {
+void ClassLinker::VisitRoots(Heap::RootVisitor* visitor, void* arg) {
   visitor(class_roots_, arg);
   Thread* self = Thread::Current();
   {
@@ -1065,6 +1074,7 @@
   }
 
   visitor(array_iftable_, arg);
+  is_dirty_ = false;
 }
 
 void ClassLinker::VisitClasses(ClassVisitor* visitor, void* arg) const {
@@ -1746,6 +1756,7 @@
   CHECK(dex_cache->GetLocation()->Equals(dex_file.GetLocation()));
   dex_caches_.push_back(dex_cache.get());
   dex_cache->SetDexFile(&dex_file);
+  Dirty();
 }
 
 void ClassLinker::RegisterDexFile(const DexFile& dex_file) {
@@ -1990,6 +2001,7 @@
     return existing;
   }
   classes.insert(std::make_pair(hash, klass));
+  Dirty();
   return NULL;
 }
 
@@ -2803,7 +2815,8 @@
   const DexFile::ClassDef* dex_class_def = kh.GetClassDef();
   CHECK(dex_class_def != NULL);
   const DexFile& dex_file = kh.GetDexFile();
-  EncodedStaticFieldValueIterator it(dex_file, dex_cache, this, *dex_class_def);
+  EncodedStaticFieldValueIterator it(dex_file, dex_cache, klass->GetClassLoader(),
+                                     this, *dex_class_def);
 
   if (it.HasNext()) {
     // We reordered the fields, so we need to be able to map the field indexes to the right fields.
diff --git a/src/class_linker.h b/src/class_linker.h
index 096d602..f1530f3 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -262,7 +262,7 @@
   void VisitClassesWithoutClassesLock(ClassVisitor* visitor, void* arg) const
       LOCKS_EXCLUDED(Locks::classlinker_classes_lock_);
 
-  void VisitRoots(Heap::RootVisitor* visitor, void* arg) const
+  void VisitRoots(Heap::RootVisitor* visitor, void* arg)
       LOCKS_EXCLUDED(Locks::classlinker_classes_lock_, dex_lock_);
 
   DexCache* FindDexCache(const DexFile& dex_file) const
@@ -302,7 +302,7 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
 
-  // Returns true if oat file contains the dex file with the given location and checksum
+  // Returns true if oat file contains the dex file with the given location and checksum.
   static bool VerifyOatFileChecksums(const OatFile* oat_file,
                                      const std::string& dex_location,
                                      uint32_t dex_location_checksum)
@@ -378,6 +378,14 @@
   pid_t GetClassesLockOwner(); // For SignalCatcher.
   pid_t GetDexLockOwner(); // For SignalCatcher.
 
+  bool IsDirty() const {
+    return is_dirty_;
+  }
+
+  void Dirty() {
+    is_dirty_ = true;
+  }
+
  private:
   explicit ClassLinker(InternTable*);
 
@@ -636,6 +644,7 @@
   IfTable* array_iftable_;
 
   bool init_done_;
+  bool is_dirty_;
 
   InternTable* intern_table_;
 
diff --git a/src/compiler.cc b/src/compiler.cc
index 1be7b75..8d7f5b6 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -839,9 +839,15 @@
   // invoked, so this can be passed to the out-of-line runtime support code.
   direct_code = 0;
   direct_method = 0;
+#if !defined(ART_USE_LLVM_COMPILER)
   if (sharp_type != kStatic && sharp_type != kDirect && sharp_type != kInterface) {
     return;
   }
+#else
+  if (sharp_type != kStatic && sharp_type != kDirect) {
+    return;
+  }
+#endif
   bool method_code_in_boot = method->GetDeclaringClass()->GetClassLoader() == NULL;
   if (!method_code_in_boot) {
     return;
diff --git a/src/compiler/codegen/GenCommon.cc b/src/compiler/codegen/GenCommon.cc
index c1d4661..21f824d 100644
--- a/src/compiler/codegen/GenCommon.cc
+++ b/src/compiler/codegen/GenCommon.cc
@@ -1321,6 +1321,10 @@
     }
   }
   /* rARG0 is ref, rARG2 is class. If ref==null, use directly as bool result */
+  RegLocation rlResult = oatGetReturn(cUnit, false);
+#if defined(TARGET_MIPS)
+  opRegCopy(cUnit, rlResult.lowReg, r_ZERO);    // store false result for if branch is taken
+#endif
   LIR* branch1 = opCmpImmBranch(cUnit, kCondEq, rARG0, 0, NULL);
   /* load object->klass_ */
   DCHECK_EQ(Object::ClassOffset().Int32Value(), 0);
@@ -1339,7 +1343,7 @@
   oatFreeTemp(cUnit, rTgt);
 #else
   /* Uses branchovers */
-  loadConstant(cUnit, rARG0, 1);     // assume true
+  loadConstant(cUnit, rlResult.lowReg, 1);     // assume true
   LIR* branchover = opCmpBranch(cUnit, kCondEq, rARG1, rARG2, NULL);
 #if !defined(TARGET_X86)
   int rTgt = loadHelper(cUnit,
@@ -1356,7 +1360,6 @@
   oatClobberCalleeSave(cUnit);
   /* branch targets here */
   LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
-  RegLocation rlResult = oatGetReturn(cUnit, false);
   storeValue(cUnit, rlDest, rlResult);
   branch1->target = target;
 #if !defined(TARGET_ARM)
@@ -1884,9 +1887,10 @@
     storeValue(cUnit, rlDest, rlResult);
   } else {
 #if defined(TARGET_MIPS)
+    rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg);
     rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg);
     if (checkZero) {
-        genNullCheck(cUnit, rlSrc2.sRegLow, rlSrc2.lowReg, 0);
+        genImmedCheck(cUnit, kCondEq, rlSrc2.lowReg, 0, kThrowDivZero);
     }
     newLIR4(cUnit, kMipsDiv, r_HI, r_LO, rlSrc1.lowReg, rlSrc2.lowReg);
     rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
@@ -1918,8 +1922,8 @@
       rlResult = oatGetReturn(cUnit, false);
     else
       rlResult = oatGetReturnAlt(cUnit);
-    storeValue(cUnit, rlDest, rlResult);
 #endif
+    storeValue(cUnit, rlDest, rlResult);
   }
   return false;
 }
diff --git a/src/compiler/codegen/mips/FP/MipsFP.cc b/src/compiler/codegen/mips/FP/MipsFP.cc
index f121a54..437f1ed 100644
--- a/src/compiler/codegen/mips/FP/MipsFP.cc
+++ b/src/compiler/codegen/mips/FP/MipsFP.cc
@@ -197,11 +197,11 @@
   oatFlushAllRegs(cUnit);
   oatLockCallTemps(cUnit);
   if (wide) {
-    loadValueDirectWideFixed(cUnit, rlSrc1, rARG0, rARG1);
-    loadValueDirectWideFixed(cUnit, rlSrc2, rARG2, rARG3);
+    loadValueDirectWideFixed(cUnit, rlSrc1, r_FARG0, r_FARG1);
+    loadValueDirectWideFixed(cUnit, rlSrc2, r_FARG2, r_FARG3);
   } else {
-    loadValueDirectFixed(cUnit, rlSrc1, rARG0);
-    loadValueDirectFixed(cUnit, rlSrc2, rARG1);
+    loadValueDirectFixed(cUnit, rlSrc1, r_FARG0);
+    loadValueDirectFixed(cUnit, rlSrc2, r_FARG2);
   }
   int rTgt = loadHelper(cUnit, offset);
   // NOTE: not a safepoint
diff --git a/src/compiler/codegen/mips/MipsLIR.h b/src/compiler/codegen/mips/MipsLIR.h
index 5e5147a..5077c9f 100644
--- a/src/compiler/codegen/mips/MipsLIR.h
+++ b/src/compiler/codegen/mips/MipsLIR.h
@@ -141,6 +141,8 @@
 /* These are the same for both big and little endian. */
 #define r_FARG0 r_F12
 #define r_FARG1 r_F13
+#define r_FARG2 r_F14
+#define r_FARG3 r_F15
 #define r_FRESULT0 r_F0
 #define r_FRESULT1 r_F1
 
diff --git a/src/compiler_llvm/gbc_expander.cc b/src/compiler_llvm/gbc_expander.cc
index 8750c0b..484dd77 100644
--- a/src/compiler_llvm/gbc_expander.cc
+++ b/src/compiler_llvm/gbc_expander.cc
@@ -60,7 +60,7 @@
  private:
   llvm::AllocaInst* shadow_frame_;
   llvm::Value* old_shadow_frame_;
-  uint32_t shadow_frame_size_;
+  uint16_t num_shadow_frame_refs_;
 
  private:
   art::Compiler* compiler_;
@@ -326,7 +326,7 @@
   GBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb)
       : llvm::FunctionPass(ID), intrinsic_helper_(intrinsic_helper), irb_(irb),
         context_(irb.getContext()), rtb_(irb.Runtime()),
-        shadow_frame_(NULL), old_shadow_frame_(NULL), shadow_frame_size_(0),
+        shadow_frame_(NULL), old_shadow_frame_(NULL), num_shadow_frame_refs_(0),
         compiler_(NULL), dex_file_(NULL), code_item_(NULL),
         oat_compilation_unit_(NULL), method_idx_(-1u), func_(NULL),
         changed_(false)
@@ -336,7 +336,7 @@
                   art::Compiler* compiler, art::OatCompilationUnit* oat_compilation_unit)
       : llvm::FunctionPass(ID), intrinsic_helper_(intrinsic_helper), irb_(irb),
         context_(irb.getContext()), rtb_(irb.Runtime()),
-        shadow_frame_(NULL), old_shadow_frame_(NULL), shadow_frame_size_(0),
+        shadow_frame_(NULL), old_shadow_frame_(NULL), num_shadow_frame_refs_(0),
         compiler_(compiler),
         dex_file_(oat_compilation_unit->GetDexFile()),
         code_item_(oat_compilation_unit->GetCodeItem()),
@@ -366,7 +366,7 @@
   // Setup rewrite context
   shadow_frame_ = NULL;
   old_shadow_frame_ = NULL;
-  shadow_frame_size_ = 0;
+  num_shadow_frame_refs_ = 0;
   func_ = &func;
   changed_ = false; // Assume unchanged
 
@@ -1095,11 +1095,11 @@
 void GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_entry_value) {
   // Most of the codes refer to MethodCompiler::EmitPrologueAllocShadowFrame and
   // MethodCompiler::EmitPushShadowFrame
-  shadow_frame_size_ =
+  num_shadow_frame_refs_ =
     llvm::cast<llvm::ConstantInt>(num_entry_value)->getZExtValue();
 
   llvm::StructType* shadow_frame_type =
-    irb_.getShadowFrameTy(shadow_frame_size_);
+    irb_.getShadowFrameTy(num_shadow_frame_refs_);
 
   shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
 
@@ -1126,7 +1126,8 @@
 
   llvm::Value* result = rtb_.EmitPushShadowFrame(shadow_frame_upcast,
                                                  method_object_addr,
-                                                 shadow_frame_size_);
+                                                 num_shadow_frame_refs_,
+                                                 0);
 
   irb_.CreateStore(result, old_shadow_frame_, kTBAARegister);
 
diff --git a/src/compiler_llvm/generated/art_module.cc b/src/compiler_llvm/generated/art_module.cc
index 872701d..e118646 100644
--- a/src/compiler_llvm/generated/art_module.cc
+++ b/src/compiler_llvm/generated/art_module.cc
@@ -93,7 +93,8 @@
 FuncTy_7_args.push_back(PointerTy_1);
 FuncTy_7_args.push_back(PointerTy_2);
 FuncTy_7_args.push_back(PointerTy_1);
-FuncTy_7_args.push_back(IntegerType::get(mod->getContext(), 32));
+FuncTy_7_args.push_back(IntegerType::get(mod->getContext(), 16));
+FuncTy_7_args.push_back(IntegerType::get(mod->getContext(), 16));
 FunctionType* FuncTy_7 = FunctionType::get(
  /*Result=*/PointerTy_2,
  /*Params=*/FuncTy_7_args,
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index 1737b70..f91694e 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -3823,7 +3823,7 @@
   } else {
     DCHECK(num_shadow_frame_refs_ == 0);
     result = irb_.Runtime().EmitPushShadowFrameNoInline(shadow_frame_upcast, method_object_addr,
-                                                        num_shadow_frame_refs_);
+                                                        num_shadow_frame_refs_, 0);
   }
   irb_.CreateStore(result, old_shadow_frame_, kTBAARegister);
 }
diff --git a/src/compiler_llvm/runtime_support_builder.cc b/src/compiler_llvm/runtime_support_builder.cc
index 2effddd..dbcbe89 100644
--- a/src/compiler_llvm/runtime_support_builder.cc
+++ b/src/compiler_llvm/runtime_support_builder.cc
@@ -124,10 +124,16 @@
 
 llvm::Value*
 RuntimeSupportBuilder::EmitPushShadowFrameNoInline(llvm::Value* new_shadow_frame,
-                                                   llvm::Value* method, uint32_t size) {
+                                                   llvm::Value* method, uint16_t num_refs,
+                                                   uint16_t num_vregs) {
   Function* func = GetRuntimeSupportFunction(runtime_support::PushShadowFrame);
   llvm::CallInst* call_inst =
-      irb_.CreateCall4(func, EmitGetCurrentThread(), new_shadow_frame, method, irb_.getInt32(size));
+      irb_.CreateCall5(func,
+                       EmitGetCurrentThread(),
+                       new_shadow_frame,
+                       method,
+                       irb_.getInt16(num_refs),
+                       irb_.getInt16(num_vregs));
   irb_.SetTBAA(call_inst, kTBAARuntimeInfo);
   return call_inst;
 }
diff --git a/src/compiler_llvm/runtime_support_builder.h b/src/compiler_llvm/runtime_support_builder.h
index b8123a5..ba512af 100644
--- a/src/compiler_llvm/runtime_support_builder.h
+++ b/src/compiler_llvm/runtime_support_builder.h
@@ -53,7 +53,7 @@
   virtual llvm::Value* EmitPushShadowFrame(llvm::Value* new_shadow_frame,
                                        llvm::Value* method, uint16_t num_refs, uint16_t num_vregs);
   virtual llvm::Value* EmitPushShadowFrameNoInline(llvm::Value* new_shadow_frame,
-                                               llvm::Value* method, uint32_t size);
+                                       llvm::Value* method, uint16_t num_refs, uint16_t num_vregs);
   virtual void EmitPopShadowFrame(llvm::Value* old_shadow_frame);
 
   /* Exception */
diff --git a/src/dex2oat.cc b/src/dex2oat.cc
index d20d7ab..20872e1 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -253,11 +253,13 @@
     Thread::Current()->TransitionFromSuspendedToRunnable();
 
     std::string image_file_location;
-    uint32_t image_file_location_checksum = 0;
+    uint32_t image_file_location_oat_checksum = 0;
+    uint32_t image_file_location_oat_begin = 0;
     Heap* heap = Runtime::Current()->GetHeap();
     if (heap->GetSpaces().size() > 1) {
       ImageSpace* image_space = heap->GetImageSpace();
-      image_file_location_checksum = image_space->GetImageHeader().GetOatChecksum();
+      image_file_location_oat_checksum = image_space->GetImageHeader().GetOatChecksum();
+      image_file_location_oat_begin = reinterpret_cast<uint32_t>(image_space->GetImageHeader().GetOatBegin());
       image_file_location = image_space->GetImageFilename();
       if (host_prefix != NULL && StartsWith(image_file_location, host_prefix->c_str())) {
         image_file_location = image_file_location.substr(host_prefix->size());
@@ -267,7 +269,8 @@
     if (!OatWriter::Create(oat_file,
                            class_loader,
                            dex_files,
-                           image_file_location_checksum,
+                           image_file_location_oat_checksum,
+                           image_file_location_oat_begin,
                            image_file_location,
                            *compiler.get())) {
       LOG(ERROR) << "Failed to create oat file " << oat_file->name();
diff --git a/src/dex_file.cc b/src/dex_file.cc
index d918152..c433f3d 100644
--- a/src/dex_file.cc
+++ b/src/dex_file.cc
@@ -901,10 +901,11 @@
 
 EncodedStaticFieldValueIterator::EncodedStaticFieldValueIterator(const DexFile& dex_file,
                                                                  DexCache* dex_cache,
+                                                                 ClassLoader* class_loader,
                                                                  ClassLinker* linker,
                                                                  const DexFile::ClassDef& class_def)
-    : dex_file_(dex_file), dex_cache_(dex_cache), linker_(linker), array_size_(), pos_(-1),
-      type_(0) {
+    : dex_file_(dex_file), dex_cache_(dex_cache), class_loader_(class_loader), linker_(linker),
+      array_size_(), pos_(-1), type_(kByte) {
   ptr_ = dex_file.GetEncodedStaticFieldValuesArray(class_def);
   if (ptr_ == NULL) {
     array_size_ = 0;
@@ -924,7 +925,7 @@
   byte value_type = *ptr_++;
   byte value_arg = value_type >> kEncodedValueArgShift;
   size_t width = value_arg + 1;  // assume and correct later
-  type_ = value_type & kEncodedValueTypeMask;
+  type_ = static_cast<ValueType>(value_type & kEncodedValueTypeMask);
   switch (type_) {
   case kBoolean:
     jval_.i = (value_arg != 0) ? 1 : 0;
@@ -956,11 +957,11 @@
     break;
   case kString:
   case kType:
-  case kMethod:
-  case kEnum:
     jval_.i = ReadUnsignedInt(ptr_, value_arg, false);
     break;
   case kField:
+  case kMethod:
+  case kEnum:
   case kArray:
   case kAnnotation:
     UNIMPLEMENTED(FATAL) << ": type " << type_;
@@ -991,6 +992,11 @@
       field->SetObject(NULL, resolved);
       break;
     }
+    case kType: {
+      Class* resolved = linker_->ResolveType(dex_file_, jval_.i, dex_cache_, class_loader_);
+      field->SetObject(NULL, resolved);
+      break;
+    }
     default: UNIMPLEMENTED(FATAL) << ": type " << type_;
   }
 }
diff --git a/src/dex_file.h b/src/dex_file.h
index cca3935..58a0b3f 100644
--- a/src/dex_file.h
+++ b/src/dex_file.h
@@ -347,7 +347,8 @@
 
   // Opens .dex file, backed by existing memory
   static const DexFile* Open(const uint8_t* base, size_t size,
-                             const std::string& location, uint32_t location_checksum) {
+                             const std::string& location,
+                             uint32_t location_checksum) {
     return OpenMemory(base, size, location, location_checksum, NULL);
   }
 
@@ -826,7 +827,8 @@
                                    MemMap* mem_map);
 
   DexFile(const byte* base, size_t size,
-          const std::string& location, uint32_t location_checksum,
+          const std::string& location,
+          uint32_t location_checksum,
           MemMap* mem_map)
       : begin_(base),
         size_(size),
@@ -1115,12 +1117,13 @@
 };
 
 class ClassLinker;
+class ClassLoader;
 class DexCache;
 class Field;
 
 class EncodedStaticFieldValueIterator {
  public:
-  EncodedStaticFieldValueIterator(const DexFile& dex_file, DexCache* dex_cache,
+  EncodedStaticFieldValueIterator(const DexFile& dex_file, DexCache* dex_cache, ClassLoader* class_loader,
                                   ClassLinker* linker, const DexFile::ClassDef& class_def)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -1131,7 +1134,6 @@
 
   void Next();
 
- private:
   enum ValueType {
     kByte = 0x00,
     kShort = 0x02,
@@ -1151,19 +1153,22 @@
     kBoolean = 0x1f
   };
 
+ private:
   static const byte kEncodedValueTypeMask = 0x1f;  // 0b11111
   static const byte kEncodedValueArgShift = 5;
 
   const DexFile& dex_file_;
   DexCache* dex_cache_;  // dex cache to resolve literal objects
+  ClassLoader* class_loader_;  // ClassLoader to resolve types
   ClassLinker* linker_;  // linker to resolve literal objects
   size_t array_size_;  // size of array
   size_t pos_;  // current position
   const byte* ptr_;  // pointer into encoded data array
-  byte type_;  // type of current encoded value
+  ValueType type_;  // type of current encoded value
   jvalue jval_;  // value of current encoded value
   DISALLOW_IMPLICIT_CONSTRUCTORS(EncodedStaticFieldValueIterator);
 };
+std::ostream& operator<<(std::ostream& os, const EncodedStaticFieldValueIterator::ValueType& code);
 
 class CatchHandlerIterator {
   public:
diff --git a/src/gc/large_object_space.cc b/src/gc/large_object_space.cc
index 72c6c73..b066dd5 100644
--- a/src/gc/large_object_space.cc
+++ b/src/gc/large_object_space.cc
@@ -267,4 +267,10 @@
   return reinterpret_cast<Object*>(addr);
 }
 
+void FreeListSpace::Dump(std::ostream& os) const{
+  os << GetName() << " -"
+     << " begin: " << reinterpret_cast<void*>(Begin())
+     << " end: " << reinterpret_cast<void*>(End());
+}
+
 }
diff --git a/src/gc/large_object_space.h b/src/gc/large_object_space.h
index 2bf6abf..979fce6 100644
--- a/src/gc/large_object_space.h
+++ b/src/gc/large_object_space.h
@@ -131,6 +131,9 @@
   size_t Size() const {
     return End() - Begin();
   }
+
+  virtual void Dump(std::ostream& os) const;
+
  private:
   static const size_t kAlignment = kPageSize;
 
diff --git a/src/gc/mark_sweep.cc b/src/gc/mark_sweep.cc
index 03bbb6a..980eed1 100644
--- a/src/gc/mark_sweep.cc
+++ b/src/gc/mark_sweep.cc
@@ -79,6 +79,8 @@
   FindDefaultMarkBitmap();
   // TODO: if concurrent, enable card marking in compiler
   // TODO: check that the mark bitmap is entirely clear.
+  // Mark any concurrent roots as dirty since we need to scan them at least once during this GC.
+  Runtime::Current()->DirtyRoots();
 }
 
 void MarkSweep::FindDefaultMarkBitmap() {
@@ -177,9 +179,9 @@
 
 void MarkSweep::VerifyRoot(const Object* root, size_t vreg, const AbstractMethod* method) {
   // See if the root is on any space bitmap.
-  if (heap_->FindSpaceFromObject(root) == NULL) {
+  if (GetHeap()->GetLiveBitmap()->GetSpaceBitmap(root) == NULL) {
     LargeObjectSpace* large_object_space = GetHeap()->GetLargeObjectsSpace();
-    if (large_object_space->Contains(root)) {
+    if (!large_object_space->Contains(root)) {
       LOG(ERROR) << "Found invalid root: " << root;
       LOG(ERROR) << "VReg / Shadow frame offset: " << vreg;
       if (method != NULL) {
@@ -195,7 +197,11 @@
 
 // Marks all objects in the root set.
 void MarkSweep::MarkRoots() {
-  Runtime::Current()->VisitRoots(MarkObjectVisitor, this);
+  Runtime::Current()->VisitNonConcurrentRoots(MarkObjectVisitor, this);
+}
+
+void MarkSweep::MarkConcurrentRoots() {
+  Runtime::Current()->VisitConcurrentRoots(MarkObjectVisitor, this);
 }
 
 class CheckObjectVisitor {
diff --git a/src/gc/mark_sweep.h b/src/gc/mark_sweep.h
index 76c5428..ed74f99 100644
--- a/src/gc/mark_sweep.h
+++ b/src/gc/mark_sweep.h
@@ -52,6 +52,9 @@
       EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  void MarkConcurrentRoots();
+      EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
+
   // Verify that image roots point to only marked objects within the alloc space.
   void VerifyImageRoots() EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
 
diff --git a/src/gc/space.cc b/src/gc/space.cc
index 4d5ce93..a7a5942 100644
--- a/src/gc/space.cc
+++ b/src/gc/space.cc
@@ -434,7 +434,6 @@
     new_size = current_space_size;
   }
   mspace_set_footprint_limit(mspace_, new_size);
-  LOG(INFO) << "Setting footprint limit to " << new_size;
 }
 
 size_t ImageSpace::bitmap_index_ = 0;
diff --git a/src/heap.cc b/src/heap.cc
index 98845d8..584c5b2 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -517,8 +517,7 @@
 
 #if VERIFY_OBJECT_ENABLED
 void Heap::VerifyObject(const Object* obj) {
-  if (obj == NULL || this == NULL || !verify_objects_ || Runtime::Current()->IsShuttingDown() ||
-      Thread::Current() == NULL ||
+  if (obj == NULL || this == NULL || !verify_objects_ || Thread::Current() == NULL ||
       Runtime::Current()->GetThreadList()->GetLockOwner() == Thread::Current()->GetTid()) {
     return;
   }
@@ -536,7 +535,9 @@
               << live_bitmap << " " << *live_bitmap << "\n"
               << mark_bitmap << " " << *mark_bitmap;
   }
-  // TODO: Dump large object space?
+  if (large_object_space_.get() != NULL) {
+    large_object_space_->Dump(LOG(INFO));
+  }
 }
 
 void Heap::VerifyObjectBody(const Object* obj) {
@@ -1045,6 +1046,7 @@
     mark_sweep.FindDefaultMarkBitmap();
 
     mark_sweep.MarkRoots();
+    mark_sweep.MarkConcurrentRoots();
     timings.AddSplit("MarkRoots");
 
     // Roots are marked on the bitmap and the mark_stack is empty.
@@ -1458,9 +1460,13 @@
     if (space->GetGcRetentionPolicy() == kGcRetentionPolicyAlwaysCollect ||
         (gc_type == kGcTypeFull &&
             space->GetGcRetentionPolicy() == kGcRetentionPolicyFullCollect)) {
-      live_bitmap_->ReplaceBitmap(space->GetLiveBitmap(), space->GetMarkBitmap());
-      mark_bitmap_->ReplaceBitmap(space->GetMarkBitmap(), space->GetLiveBitmap());
-      space->AsAllocSpace()->SwapBitmaps();
+      SpaceBitmap* live_bitmap = space->GetLiveBitmap();
+      SpaceBitmap* mark_bitmap = space->GetMarkBitmap();
+      if (live_bitmap != mark_bitmap) {
+        live_bitmap_->ReplaceBitmap(live_bitmap, mark_bitmap);
+        mark_bitmap_->ReplaceBitmap(mark_bitmap, live_bitmap);
+        space->AsAllocSpace()->SwapBitmaps();
+      }
     }
   }
   SwapLargeObjects();
@@ -1615,6 +1621,10 @@
       root_end = NanoTime();
       timings.AddSplit("RootEnd");
 
+      // Mark the roots which we can do concurrently.
+      mark_sweep.MarkConcurrentRoots();
+      timings.AddSplit("MarkConcurrentRoots");
+
       WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
       UpdateAndMarkModUnion(&mark_sweep, timings, gc_type);
 
@@ -1695,11 +1705,12 @@
 
     if (verify_post_gc_heap_) {
       WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
-      SwapBitmaps(gc_type);
+      // Swapping bound bitmaps does nothing.
+      SwapBitmaps(kGcTypeFull);
       if (!VerifyHeapReferences()) {
         LOG(FATAL) << "Post " << gc_type_str.str() << "Gc verification failed";
       }
-      SwapBitmaps(gc_type);
+      SwapBitmaps(kGcTypeFull);
       timings.AddSplit("VerifyHeapReferencesPostGC");
     }
 
@@ -2029,8 +2040,7 @@
   }
 }
 
-void Heap::Trim(Thread* self) {
-  WaitForConcurrentGcToComplete(self);
+void Heap::Trim() {
   alloc_space_->Trim();
 }
 
diff --git a/src/heap.h b/src/heap.h
index 14d8382..984a329 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -278,7 +278,7 @@
 
   void DumpForSigQuit(std::ostream& os);
 
-  void Trim(Thread* self);
+  void Trim();
 
   HeapBitmap* GetLiveBitmap() SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) {
     return live_bitmap_.get();
diff --git a/src/image.h b/src/image.h
index 399b143..852367d 100644
--- a/src/image.h
+++ b/src/image.h
@@ -71,6 +71,10 @@
     return oat_checksum_;
   }
 
+  void SetOatChecksum(uint32_t oat_checksum) {
+    oat_checksum_ = oat_checksum;
+  }
+
   byte* GetOatBegin() const {
     return reinterpret_cast<byte*>(oat_begin_);
   }
diff --git a/src/image_test.cc b/src/image_test.cc
index 05ddc54..afccb4a 100644
--- a/src/image_test.cc
+++ b/src/image_test.cc
@@ -36,7 +36,7 @@
     ScopedObjectAccess soa(Thread::Current());
     std::vector<const DexFile*> dex_files;
     dex_files.push_back(java_lang_dex_file_);
-    bool success_oat = OatWriter::Create(tmp_oat.GetFile(), NULL, dex_files, 0, "", *compiler_.get());
+    bool success_oat = OatWriter::Create(tmp_oat.GetFile(), NULL, dex_files, 0, 0, "", *compiler_.get());
     ASSERT_TRUE(success_oat);
 
     // Force all system classes into memory
diff --git a/src/image_writer.cc b/src/image_writer.cc
index 56dfa5e..497ca22 100644
--- a/src/image_writer.cc
+++ b/src/image_writer.cc
@@ -676,6 +676,10 @@
     AbstractMethod* target = GetTargetMethod(patch);
     SetPatchLocation(patch, reinterpret_cast<uint32_t>(GetImageAddress(target)));
   }
+
+  // Update the image header with the new checksum after patching
+  ImageHeader* image_header = reinterpret_cast<ImageHeader*>(image_->Begin());
+  image_header->SetOatChecksum(oat_file_->GetOatHeader().GetChecksum());
 }
 
 void ImageWriter::SetPatchLocation(const Compiler::PatchInformation* patch, uint32_t value) {
@@ -683,6 +687,7 @@
   AbstractMethod* method = GetReferrerMethod(patch);
   // Goodbye const, we are about to modify some code.
   void* code = const_cast<void*>(class_linker->GetOatCodeFor(method));
+  OatHeader& oat_header = const_cast<OatHeader&>(oat_file_->GetOatHeader());
   // TODO: make this Thumb2 specific
   uint8_t* base = reinterpret_cast<uint8_t*>(reinterpret_cast<uint32_t>(code) & ~0x1);
   uint32_t* patch_location = reinterpret_cast<uint32_t*>(base + patch->GetLiteralOffset());
@@ -696,6 +701,7 @@
     << "value=" << value;
 #endif
   *patch_location = value;
+  oat_header.UpdateChecksum(patch_location, sizeof(value));
 }
 
 }  // namespace art
diff --git a/src/intern_table.cc b/src/intern_table.cc
index 5ad3958..817ce1e 100644
--- a/src/intern_table.cc
+++ b/src/intern_table.cc
@@ -21,7 +21,7 @@
 
 namespace art {
 
-InternTable::InternTable() : intern_table_lock_("InternTable lock") {
+InternTable::InternTable() : intern_table_lock_("InternTable lock"), is_dirty_(false) {
 }
 
 size_t InternTable::Size() const {
@@ -36,12 +36,13 @@
      << image_strong_interns_.size() << " image strong\n";
 }
 
-void InternTable::VisitRoots(Heap::RootVisitor* visitor, void* arg) const {
+void InternTable::VisitRoots(Heap::RootVisitor* visitor, void* arg) {
   MutexLock mu(Thread::Current(), intern_table_lock_);
   typedef Table::const_iterator It; // TODO: C++0x auto
   for (It it = strong_interns_.begin(), end = strong_interns_.end(); it != end; ++it) {
     visitor(it->second, arg);
   }
+  is_dirty_ = false;
   // Note: we deliberately don't visit the weak_interns_ table and the immutable image roots.
 }
 
@@ -97,6 +98,9 @@
       return image;
     }
 
+    // Mark as dirty so that we rescan the roots.
+    Dirty();
+
     // There is no match in the strong table, check the weak table.
     String* weak = Lookup(weak_interns_, s, hash_code);
     if (weak != NULL) {
diff --git a/src/intern_table.h b/src/intern_table.h
index 6f56773..93d20b2 100644
--- a/src/intern_table.h
+++ b/src/intern_table.h
@@ -65,10 +65,15 @@
 
   size_t Size() const;
 
-  void VisitRoots(Heap::RootVisitor* visitor, void* arg) const;
+  void VisitRoots(Heap::RootVisitor* visitor, void* arg);
 
   void DumpForSigQuit(std::ostream& os) const;
 
+  bool IsDirty() const { return is_dirty_; }
+  void Dirty() {
+    is_dirty_ = true;
+  }
+
  private:
   typedef std::multimap<int32_t, String*> Table;
 
@@ -81,6 +86,7 @@
   void Remove(Table& table, const String* s, uint32_t hash_code);
 
   mutable Mutex intern_table_lock_;
+  bool is_dirty_;
   Table image_strong_interns_ GUARDED_BY(intern_table_lock_);
   Table strong_interns_ GUARDED_BY(intern_table_lock_);
   Table weak_interns_ GUARDED_BY(intern_table_lock_);
diff --git a/src/native/dalvik_system_DexFile.cc b/src/native/dalvik_system_DexFile.cc
index 3ef5e5c..a55d7f1 100644
--- a/src/native/dalvik_system_DexFile.cc
+++ b/src/native/dalvik_system_DexFile.cc
@@ -244,10 +244,18 @@
     if ((*cur)->IsImageSpace()) {
       // TODO: Ensure this works with multiple image spaces.
       const ImageHeader& image_header = (*cur)->AsImageSpace()->GetImageHeader();
-      if (oat_file->GetOatHeader().GetImageFileLocationChecksum() != image_header.GetOatChecksum()) {
+      if (oat_file->GetOatHeader().GetImageFileLocationOatChecksum() != image_header.GetOatChecksum()) {
         ScopedObjectAccess soa(env);
         LOG(INFO) << "DexFile_isDexOptNeeded cache file " << cache_location
-                  << " has out-of-date checksum compared to "
+                  << " has out-of-date oat checksum compared to "
+                  << image_header.GetImageRoot(ImageHeader::kOatLocation)->AsString()->ToModifiedUtf8();
+        return JNI_TRUE;
+      }
+      if (oat_file->GetOatHeader().GetImageFileLocationOatBegin()
+          != reinterpret_cast<uint32_t>(image_header.GetOatBegin())) {
+        ScopedObjectAccess soa(env);
+        LOG(INFO) << "DexFile_isDexOptNeeded cache file " << cache_location
+                  << " has out-of-date oat begin compared to "
                   << image_header.GetImageRoot(ImageHeader::kOatLocation)->AsString()->ToModifiedUtf8();
         return JNI_TRUE;
       }
diff --git a/src/native/dalvik_system_VMRuntime.cc b/src/native/dalvik_system_VMRuntime.cc
index b98f974..9c40041 100644
--- a/src/native/dalvik_system_VMRuntime.cc
+++ b/src/native/dalvik_system_VMRuntime.cc
@@ -156,15 +156,14 @@
   }
 }
 
-static void VMRuntime_trimHeap(JNIEnv* env, jobject) {
+static void VMRuntime_trimHeap(JNIEnv*, jobject) {
   // Trim the managed heap.
   Heap* heap = Runtime::Current()->GetHeap();
   uint64_t start_ns = NanoTime();
   DlMallocSpace* alloc_space = heap->GetAllocSpace();
   size_t alloc_space_size = alloc_space->Size();
   float utilization = static_cast<float>(alloc_space->GetNumBytesAllocated()) / alloc_space_size;
-  Thread* self = static_cast<JNIEnvExt*>(env)->self;
-  heap->Trim(self);
+  heap->Trim();
   // Trim the native heap.
   dlmalloc_trim(0);
   dlmalloc_inspect_all(MspaceMadviseCallback, NULL);
diff --git a/src/native/dalvik_system_Zygote.cc b/src/native/dalvik_system_Zygote.cc
index 68ae7db..8b14117e 100644
--- a/src/native/dalvik_system_Zygote.cc
+++ b/src/native/dalvik_system_Zygote.cc
@@ -36,9 +36,7 @@
 #include <sys/prctl.h>
 #endif
 
-#if defined(HAVE_SELINUX)
 #include <selinux/android.h>
-#endif
 
 #if defined(__linux__)
 #include <sys/personality.h>
@@ -340,6 +338,9 @@
 
 #if defined(__linux__)
 static bool NeedsNoRandomizeWorkaround() {
+#if !defined(__arm__)
+    return false;
+#else
     int major;
     int minor;
     struct utsname uts;
@@ -353,6 +354,7 @@
 
     // Kernels before 3.4.* need the workaround.
     return (major < 3) || ((major == 3) && (minor < 4));
+#endif
 }
 #endif
 
@@ -416,17 +418,27 @@
 
     SetSchedulerPolicy();
 
-#if defined(HAVE_SELINUX) && defined(HAVE_ANDROID_OS)
+#if defined(HAVE_ANDROID_OS)
     {
-      ScopedUtfChars se_info(env, java_se_info);
-      CHECK(se_info != NULL);
-      ScopedUtfChars se_name(env, java_se_name);
-      CHECK(se_name != NULL);
-      rc = selinux_android_setcontext(uid, is_system_server, se_info, se_name);
+      const char* se_info_c_str = NULL;
+      UniquePtr<ScopedUtfChars> se_info;
+      if (java_se_info != NULL) {
+          se_info.reset(new ScopedUtfChars(env, java_se_info));
+          se_info_c_str = se_info->c_str();
+          CHECK(se_info_c_str != NULL);
+      }
+      const char* se_name_c_str = NULL;
+      UniquePtr<ScopedUtfChars> se_name;
+      if (java_se_name != NULL) {
+          se_name.reset(new ScopedUtfChars(env, java_se_name));
+          se_name_c_str = se_name->c_str();
+          CHECK(se_name_c_str != NULL);
+      }
+      rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
       if (rc == -1) {
         PLOG(FATAL) << "selinux_android_setcontext(" << uid << ", "
                     << (is_system_server ? "true" : "false") << ", "
-                    << "\"" << se_info << "\", \"" << se_name << "\") failed";
+                    << "\"" << se_info_c_str << "\", \"" << se_name_c_str << "\") failed";
       }
     }
 #else
diff --git a/src/native/java_lang_Object.cc b/src/native/java_lang_Object.cc
index a6ae49d..bcea373 100644
--- a/src/native/java_lang_Object.cc
+++ b/src/native/java_lang_Object.cc
@@ -45,7 +45,7 @@
 }
 
 static JNINativeMethod gMethods[] = {
-  NATIVE_METHOD(Object, internalClone, "(Ljava/lang/Cloneable;)Ljava/lang/Object;"),
+  NATIVE_METHOD(Object, internalClone, "()Ljava/lang/Object;"),
   NATIVE_METHOD(Object, notify, "()V"),
   NATIVE_METHOD(Object, notifyAll, "()V"),
   NATIVE_METHOD(Object, wait, "(JI)V"),
diff --git a/src/oat.cc b/src/oat.cc
index 4df4543..a328a11 100644
--- a/src/oat.cc
+++ b/src/oat.cc
@@ -21,7 +21,7 @@
 namespace art {
 
 const uint8_t OatHeader::kOatMagic[] = { 'o', 'a', 't', '\n' };
-const uint8_t OatHeader::kOatVersion[] = { '0', '0', '2', '\0' };
+const uint8_t OatHeader::kOatVersion[] = { '0', '0', '3', '\0' };
 
 OatHeader::OatHeader() {
   memset(this, 0, sizeof(*this));
@@ -29,21 +29,27 @@
 
 OatHeader::OatHeader(InstructionSet instruction_set,
                      const std::vector<const DexFile*>* dex_files,
-                     uint32_t image_file_location_checksum,
+                     uint32_t image_file_location_oat_checksum,
+                     uint32_t image_file_location_oat_begin,
                      const std::string& image_file_location) {
   memcpy(magic_, kOatMagic, sizeof(kOatMagic));
   memcpy(version_, kOatVersion, sizeof(kOatVersion));
 
   adler32_checksum_ = adler32(0L, Z_NULL, 0);
 
+  CHECK_NE(instruction_set, kNone);
   instruction_set_ = instruction_set;
   UpdateChecksum(&instruction_set_, sizeof(instruction_set_));
 
   dex_file_count_ = dex_files->size();
   UpdateChecksum(&dex_file_count_, sizeof(dex_file_count_));
 
-  image_file_location_checksum_ = image_file_location_checksum;
-  UpdateChecksum(&image_file_location_checksum_, sizeof(image_file_location_checksum_));
+  image_file_location_oat_checksum_ = image_file_location_oat_checksum;
+  UpdateChecksum(&image_file_location_oat_checksum_, sizeof(image_file_location_oat_checksum_));
+
+  CHECK(IsAligned<kPageSize>(image_file_location_oat_begin));
+  image_file_location_oat_begin_ = image_file_location_oat_begin;
+  UpdateChecksum(&image_file_location_oat_begin_, sizeof(image_file_location_oat_begin_));
 
   image_file_location_size_ = image_file_location.size();
   UpdateChecksum(&image_file_location_size_, sizeof(image_file_location_size_));
@@ -53,10 +59,10 @@
 }
 
 bool OatHeader::IsValid() const {
-  if (memcmp(magic_, kOatMagic, sizeof(kOatMagic) != 0)) {
+  if (memcmp(magic_, kOatMagic, sizeof(kOatMagic)) != 0) {
     return false;
   }
-  if (memcmp(version_, kOatVersion, sizeof(kOatVersion) != 0)) {
+  if (memcmp(version_, kOatVersion, sizeof(kOatVersion)) != 0) {
     return false;
   }
   return true;
@@ -95,9 +101,14 @@
   return executable_offset_;
 }
 
-uint32_t OatHeader::GetImageFileLocationChecksum() const {
+uint32_t OatHeader::GetImageFileLocationOatChecksum() const {
   CHECK(IsValid());
-  return image_file_location_checksum_;
+  return image_file_location_oat_checksum_;
+}
+
+uint32_t OatHeader::GetImageFileLocationOatBegin() const {
+  CHECK(IsValid());
+  return image_file_location_oat_begin_;
 }
 
 uint32_t OatHeader::GetImageFileLocationSize() const {
diff --git a/src/oat.h b/src/oat.h
index cd3330b..96ed4c4 100644
--- a/src/oat.h
+++ b/src/oat.h
@@ -30,7 +30,8 @@
   OatHeader();
   OatHeader(InstructionSet instruction_set,
             const std::vector<const DexFile*>* dex_files,
-            uint32_t image_file_location_checksum,
+            uint32_t image_file_location_oat_checksum,
+            uint32_t image_file_location_oat_begin,
             const std::string& image_file_location);
 
   bool IsValid() const;
@@ -41,7 +42,8 @@
   uint32_t GetExecutableOffset() const;
   InstructionSet GetInstructionSet() const;
   void SetExecutableOffset(uint32_t executable_offset);
-  uint32_t GetImageFileLocationChecksum() const;
+  uint32_t GetImageFileLocationOatChecksum() const;
+  uint32_t GetImageFileLocationOatBegin() const;
   uint32_t GetImageFileLocationSize() const;
   const uint8_t* GetImageFileLocationData() const;
   std::string GetImageFileLocation() const;
@@ -58,7 +60,8 @@
   uint32_t dex_file_count_;
   uint32_t executable_offset_;
 
-  uint32_t image_file_location_checksum_;
+  uint32_t image_file_location_oat_checksum_;
+  uint32_t image_file_location_oat_begin_;
   uint32_t image_file_location_size_;
   uint8_t image_file_location_data_[0];  // note variable width data at end
 
diff --git a/src/oat/runtime/mips/oat_support_entrypoints_mips.cc b/src/oat/runtime/mips/oat_support_entrypoints_mips.cc
index 334ca95..458933f 100644
--- a/src/oat/runtime/mips/oat_support_entrypoints_mips.cc
+++ b/src/oat/runtime/mips/oat_support_entrypoints_mips.cc
@@ -84,6 +84,9 @@
 extern int32_t CmplDouble(double a, double b);
 extern int32_t CmpgFloat(float a, float b);
 extern int32_t CmplFloat(float a, float b);
+extern "C" int64_t artLmulFromCode(int64_t a, int64_t b);
+extern "C" int64_t artLdivFromCode(int64_t a, int64_t b);
+extern "C" int64_t artLdivmodFromCode(int64_t a, int64_t b);
 
 // Math conversions.
 extern "C" float __floatsisf(int op1);        // INT_TO_FLOAT
@@ -233,9 +236,9 @@
   points->pIdivmod = NULL;
   points->pD2l = art_d2l;
   points->pF2l = art_f2l;
-  points->pLdiv = NULL;
-  points->pLdivmod = NULL;
-  points->pLmul = NULL;
+  points->pLdiv = artLdivFromCode;
+  points->pLdivmod = artLdivmodFromCode;
+  points->pLmul = artLmulFromCode;
   points->pShlLong = art_shl_long;
   points->pShrLong = art_shr_long;
   points->pUshrLong = art_ushr_long;
diff --git a/src/oat/runtime/mips/runtime_support_mips.S b/src/oat/runtime/mips/runtime_support_mips.S
index cbf895a..eafd380 100644
--- a/src/oat/runtime/mips/runtime_support_mips.S
+++ b/src/oat/runtime/mips/runtime_support_mips.S
@@ -53,30 +53,32 @@
      * Macro that sets up the callee save frame to conform with
      * Runtime::CreateCalleeSaveMethod(kRefsOnly). Restoration assumes non-moving GC.
      * Does not include rSUSPEND or rSELF
-     * callee-save: $s2-$s8 + $ra, 8 total + 4 words
+     * callee-save: $s2-$s8 + $ra, 8 total + 4 words + extra args + gp
      */
 .macro SETUP_REF_ONLY_CALLEE_SAVE_FRAME
-    addiu  $sp, $sp, -48
-    sw     $ra, 44($sp)
-    sw     $s8, 40($sp)
-    sw     $s7, 36($sp)
-    sw     $s6, 32($sp)
-    sw     $s5, 28($sp)
-    sw     $s4, 24($sp)
-    sw     $s3, 20($sp)
-    sw     $s2, 16($sp)
-    # 4 open words for args $a0-$a3, bottom will hold Method*
+    addiu  $sp, $sp, -64
+    sw     $ra, 60($sp)
+    sw     $s8, 56($sp)
+    sw     $s7, 52($sp)
+    sw     $s6, 48($sp)
+    sw     $s5, 44($sp)
+    sw     $s4, 40($sp)
+    sw     $s3, 36($sp)
+    sw     $s2, 32($sp)
+    sw     $gp, 28($sp)
+    # 3 words for alignment and extra args, 4 open words for args $a0-$a3, bottom will hold Method*
 .endm
 
 .macro RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
-    lw     $ra, 44($sp)
-    addiu  $sp, $sp, 48
+    lw     $gp, 28($sp)
+    lw     $ra, 60($sp)
+    addiu  $sp, $sp, 64
 .endm
 
 .macro RESTORE_REF_ONLY_CALLEE_SAVE_FRAME_AND_RETURN
-    lw     $ra, 44($sp)
+    lw     $ra, 60($sp)
     jr     $ra
-    addiu  $sp, $sp, 48
+    addiu  $sp, $sp, 64
 .endm
 
     /*
@@ -304,9 +306,9 @@
 art_throw_stack_overflow_from_code:
     .cpload $25
     SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
-    move $a1, rSELF                    # pass Thread::Current
-    jal artThrowStackOverflowFromCode  # artThrowStackOverflowFromCode(method, Thread*, $sp)
-    move $a2, $sp                      # pass $sp
+    move $a0, rSELF                    # pass Thread::Current
+    jal artThrowStackOverflowFromCode  # artThrowStackOverflowFromCode(Thread*, $sp)
+    move $a1, $sp                      # pass $sp
 
     .global art_throw_no_such_method_from_code
     .extern artThrowNoSuchMethodFromCode
@@ -409,13 +411,7 @@
     move    $a2, rSELF                         # pass Thread::Current
     jal     artHandleFillArrayDataFromCode     # (Array*, const DexFile::Payload*, Thread*, $sp)
     move    $a3, $sp                           # pass $sp
-    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
-    bnez    $v0, 1f                            # success?
-    nop
-    jr      $ra                                # return on success
-    nop
-1:
-    DELIVER_PENDING_EXCEPTION
+    RETURN_IF_ZERO
 
     .global art_lock_object_from_code
     .extern artLockObjectFromCode
@@ -531,7 +527,7 @@
 art_get32_static_from_code:
     .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
-    lw     $a1, 48($sp)                  # pass referrer's Method*
+    lw     $a1, 64($sp)                  # pass referrer's Method*
     move   $a2, rSELF                    # pass Thread::Current
     jal    artGet32StaticFromCode        # (uint32_t field_idx, const Method* referrer, Thread*, $sp)
     move   $a3, $sp                      # pass $sp
@@ -546,7 +542,7 @@
 art_get64_static_from_code:
     .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
-    lw     $a1, 48($sp)                  # pass referrer's Method*
+    lw     $a1, 64($sp)                  # pass referrer's Method*
     move   $a2, rSELF                    # pass Thread::Current
     jal    artGet64StaticFromCode        # (uint32_t field_idx, const Method* referrer, Thread*, $sp)
     move   $a3, $sp                      # pass $sp
@@ -561,7 +557,7 @@
 art_get_obj_static_from_code:
     .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
-    lw     $a1, 48($sp)                  # pass referrer's Method*
+    lw     $a1, 64($sp)                  # pass referrer's Method*
     move   $a2, rSELF                    # pass Thread::Current
     jal    artGetObjStaticFromCode       # (uint32_t field_idx, const Method* referrer, Thread*, $sp)
     move   $a3, $sp                      # pass $sp
@@ -576,13 +572,10 @@
 art_get32_instance_from_code:
     .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
-    lw     $a2, 48($sp)                  # pass referrer's Method*
-    move   $t0, $sp                      # save $sp
-    addiu  $sp, $sp, -16                 # make space for extra args
+    lw     $a2, 64($sp)                  # pass referrer's Method*
     move   $a3, rSELF                    # pass Thread::Current
     jal    artGet32InstanceFromCode      # (field_idx, Object*, referrer, Thread*, $sp)
-    sw     $t0, 16($sp)                  # pass $sp
-    addiu  $sp, $sp, 16                  # release out args
+    sw     $sp, 16($sp)                  # pass $sp
     RETURN_IF_NO_EXCEPTION
 
     .global art_get64_instance_from_code
@@ -594,13 +587,10 @@
 art_get64_instance_from_code:
     .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
-    lw     $a2, 48($sp)                  # pass referrer's Method*
-    move   $t0, $sp                      # save $sp
-    addiu  $sp, $sp, -16                 # make space for extra args
+    lw     $a2, 64($sp)                  # pass referrer's Method*
     move   $a3, rSELF                    # pass Thread::Current
     jal    artGet64InstanceFromCode      # (field_idx, Object*, referrer, Thread*, $sp)
-    sw     $t0, 16($sp)                  # pass $sp
-    addiu  $sp, $sp, 16                  # release out args
+    sw     $sp, 16($sp)                  # pass $sp
     RETURN_IF_NO_EXCEPTION
 
     .global art_get_obj_instance_from_code
@@ -612,13 +602,10 @@
 art_get_obj_instance_from_code:
     .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
-    lw     $a2, 48($sp)                  # pass referrer's Method*
-    move   $t0, $sp                      # save $sp
-    addiu  $sp, $sp, -16                 # make space for extra args
+    lw     $a2, 64($sp)                  # pass referrer's Method*
     move   $a3, rSELF                    # pass Thread::Current
     jal    artGetObjInstanceFromCode     # (field_idx, Object*, referrer, Thread*, $sp)
-    sw     $t0, 16($sp)                  # pass $sp
-    addiu  $sp, $sp, 16                  # release out args
+    sw     $sp, 16($sp)                  # pass $sp
     RETURN_IF_NO_EXCEPTION
 
     .global art_set32_static_from_code
@@ -630,13 +617,10 @@
 art_set32_static_from_code:
     .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
-    lw     $a2, 48($sp)                  # pass referrer's Method*
-    move   $t0, $sp                      # save $sp
-    addiu  $sp, $sp, -16                 # make space for extra args
+    lw     $a2, 64($sp)                  # pass referrer's Method*
     move   $a3, rSELF                    # pass Thread::Current
     jal    artSet32StaticFromCode        # (field_idx, new_val, referrer, Thread*, $sp)
-    sw     $t0, 16($sp)                  # pass $sp
-    addiu  $sp, $sp, 16                  # release out args
+    sw     $sp, 16($sp)                  # pass $sp
     RETURN_IF_ZERO
 
     .global art_set64_static_from_code
@@ -648,13 +632,10 @@
 art_set64_static_from_code:
     .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
-    lw     $a1, 48($sp)                  # pass referrer's Method*
-    move   $t0, $sp                      # save $sp
-    addiu  $sp, $sp, -16                 # make space for extra args
+    lw     $a1, 64($sp)                  # pass referrer's Method*
     sw     rSELF, 16($sp)                # pass Thread::Current
     jal    artSet64StaticFromCode        # (field_idx, referrer, new_val, Thread*, $sp)
-    sw     $t0, 20($sp)                  # pass $sp
-    addiu  $sp, $sp, 16                  # release out args
+    sw     $sp, 20($sp)                  # pass $sp
     RETURN_IF_ZERO
 
     .global art_set_obj_static_from_code
@@ -666,13 +647,10 @@
 art_set_obj_static_from_code:
     .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
-    lw     $a2, 48($sp)                  # pass referrer's Method*
-    move   $t0, $sp                      # save $sp
-    addiu  $sp, $sp, -16                 # make space for extra args
+    lw     $a2, 64($sp)                  # pass referrer's Method*
     move   $a3, rSELF                    # pass Thread::Current
     jal    artSetObjStaticFromCode       # (field_idx, new_val, referrer, Thread*, $sp)
-    sw     $t0, 16($sp)                  # pass $sp
-    addiu  $sp, $sp, 16                  # release out args
+    sw     $sp, 16($sp)                  # pass $sp
     RETURN_IF_ZERO
 
     .global art_set32_instance_from_code
@@ -684,13 +662,10 @@
 art_set32_instance_from_code:
     .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
-    lw     $a3, 48($sp)                  # pass referrer's Method*
-    move   $t0, $sp                      # save $sp
-    addiu  $sp, $sp, -16                 # make space for extra args
+    lw     $a3, 64($sp)                  # pass referrer's Method*
     sw     rSELF, 16($sp)                # pass Thread::Current
     jal    artSet32InstanceFromCode      # (field_idx, Object*, new_val, referrer, Thread*, $sp)
-    sw     $t0, 20($sp)                  # pass $sp
-    addiu  $sp, $sp, 16                  # release out args
+    sw     $sp, 20($sp)                  # pass $sp
     RETURN_IF_ZERO
 
     .global art_set64_instance_from_code
@@ -702,12 +677,9 @@
 art_set64_instance_from_code:
     .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
-    move   $t0, $sp                      # save $sp
-    addiu  $sp, $sp, -16                 # make space for extra args
     sw     rSELF, 16($sp)                # pass Thread::Current
     jal    artSet64InstanceFromCode      # (field_idx, Object*, new_val, Thread*, $sp)
-    sw     $t0, 20($sp)                  # pass $sp
-    addiu  $sp, $sp, 16                  # release out args
+    sw     $sp, 20($sp)                  # pass $sp
     RETURN_IF_ZERO
 
     .global art_set_obj_instance_from_code
@@ -719,13 +691,10 @@
 art_set_obj_instance_from_code:
     .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     # save callee saves in case of GC
-    lw     $a3, 48($sp)                  # pass referrer's Method*
-    move   $t0, $sp                      # save $sp
-    addiu  $sp, $sp, -16                 # make space for extra args
+    lw     $a3, 64($sp)                  # pass referrer's Method*
     sw     rSELF, 16($sp)                # pass Thread::Current
     jal    artSetObjInstanceFromCode     # (field_idx, Object*, new_val, referrer, Thread*, $sp)
-    sw     $t0, 20($sp)                  # pass $sp
-    addiu  $sp, $sp, 16                  # release out args
+    sw     $sp, 20($sp)                  # pass $sp
     RETURN_IF_ZERO
 
     .global art_resolve_string_from_code
@@ -785,12 +754,9 @@
     .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  # save callee saves in case of GC
     move    $a3, rSELF                # pass Thread::Current
-    move    $t0, $sp                  # save $sp
-    addiu   $sp, $sp, -16             # make space for extra args
     # artAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count, Thread*, $sp)
     jal     artAllocArrayFromCode
-    sw      $t0, 16($sp)              # pass $sp
-    addiu   $sp, $sp, 16              # release out args
+    sw      $sp, 16($sp)              # pass $sp
     RETURN_IF_NONZERO
 
     .global art_alloc_array_from_code_with_access_check
@@ -804,12 +770,9 @@
     .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  # save callee saves in case of GC
     move    $a3, rSELF                # pass Thread::Current
-    move    $t0, $sp                  # save $sp
-    addiu   $sp, $sp, -16             # make space for extra args
     # artAllocArrayFromCodeWithAccessCheck(type_idx, method, component_count, Thread*, $sp)
     jal     artAllocArrayFromCodeWithAccessCheck
-    sw      $t0, 16($sp)              # pass $sp
-    addiu   $sp, $sp, 16              # release out args
+    sw      $sp, 16($sp)              # pass $sp
     RETURN_IF_NONZERO
 
     .global art_check_and_alloc_array_from_code
@@ -822,12 +785,9 @@
     .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  # save callee saves in case of GC
     move    $a3, rSELF                # pass Thread::Current
-    move    $t0, $sp                  # save $sp
-    addiu   $sp, $sp, -16             # make space for extra args
     # artCheckAndAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t count, Thread* , $sp)
     jal     artCheckAndAllocArrayFromCode
-    sw      $t0, 16($sp)              # pass $sp
-    addiu   $sp, $sp, 16              # release out args
+    sw      $sp, 16($sp)              # pass $sp
     RETURN_IF_NONZERO
 
     .global art_check_and_alloc_array_from_code_with_access_check
@@ -840,12 +800,9 @@
     .cpload $25
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  # save callee saves in case of GC
     move    $a3, rSELF                # pass Thread::Current
-    move    $t0, $sp                  # save $sp
-    addiu   $sp, $sp, -16             # make space for extra args
     # artCheckAndAllocArrayFromCodeWithAccessCheck(type_idx, method, count, Thread* , $sp)
     jal     artCheckAndAllocArrayFromCodeWithAccessCheck
-    sw      $t0, 16($sp)              # pass $sp
-    addiu   $sp, $sp, 16              # release out args
+    sw      $sp, 16($sp)              # pass $sp
     RETURN_IF_NONZERO
 
     .global art_test_suspend
@@ -855,6 +812,7 @@
      */
     ALIGN_FUNCTION_ENTRY
 art_test_suspend:
+    .cpload $25
     lh     $a0, THREAD_FLAGS_OFFSET(rSELF)
     bnez   $a0, 1f
     addi  rSUSPEND, $zero, SUSPEND_CHECK_INTERVAL   # reset rSUSPEND to SUSPEND_CHECK_INTERVAL
@@ -958,7 +916,7 @@
     andi    $a2, 0x20                        #  shift< shift & 0x20
     movn    $v1, $v0, $a2                    #  rhi<- rlo (if shift&0x20)
     jr      $ra
-    movn    $v0, $zero, $a2                   #  rlo<- 0  (if shift&0x20)
+    movn    $v0, $zero, $a2                  #  rlo<- 0  (if shift&0x20)
 
     .global art_shr_long
     /*
@@ -999,9 +957,8 @@
     /* ushr-long vAA, vBB, vCC */
     ALIGN_FUNCTION_ENTRY
 art_ushr_long:
-    sra     $v1, $a1, $a2                    #  rhi<- ahi >> (shift&31)
+    srl     $v1, $a1, $a2                    #  rhi<- ahi >> (shift&31)
     srl     $v0, $a0, $a2                    #  rlo<- alo >> (shift&31)
-    sra     $a3, $a1, 31                     #  $a3<- sign(ah)
     not     $a0, $a2                         #  alo<- 31-shift (shift is 5b)
     sll     $a1, 1
     sll     $a1, $a0                         #  ahi<- ahi << (32-(shift&31))
@@ -1009,7 +966,7 @@
     andi    $a2, 0x20                        #  shift & 0x20
     movn    $v0, $v1, $a2                    #  rlo<- rhi (if shift&0x20)
     jr      $ra
-    movn    $v1, $a3, $a2                    #  rhi<- sign(ahi) (if shift&0x20)
+    movn    $v1, $zero, $a2                  #  rhi<- 0 (if shift&0x20)
 
     .global art_indexof
     ALIGN_FUNCTION_ENTRY
diff --git a/src/oat/runtime/mips/stub_mips.cc b/src/oat/runtime/mips/stub_mips.cc
index 9fd65c8..b04979b 100644
--- a/src/oat/runtime/mips/stub_mips.cc
+++ b/src/oat/runtime/mips/stub_mips.cc
@@ -126,15 +126,17 @@
   UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips)));
 #if !defined(ART_USE_LLVM_COMPILER)
   // Save callee saves and ready frame for exception delivery
-  __ AddConstant(SP, SP, -48);
-  __ StoreToOffset(kStoreWord, RA, SP, 44);
-  __ StoreToOffset(kStoreWord, FP, SP, 40);
-  __ StoreToOffset(kStoreWord, S7, SP, 36);
-  __ StoreToOffset(kStoreWord, S6, SP, 32);
-  __ StoreToOffset(kStoreWord, S5, SP, 28);
-  __ StoreToOffset(kStoreWord, S4, SP, 24);
-  __ StoreToOffset(kStoreWord, S3, SP, 20);
-  __ StoreToOffset(kStoreWord, S2, SP, 16);
+  __ AddConstant(SP, SP, -64);
+  __ StoreToOffset(kStoreWord, RA, SP, 60);
+  __ StoreToOffset(kStoreWord, FP, SP, 56);
+  __ StoreToOffset(kStoreWord, S7, SP, 52);
+  __ StoreToOffset(kStoreWord, S6, SP, 48);
+  __ StoreToOffset(kStoreWord, S5, SP, 44);
+  __ StoreToOffset(kStoreWord, S4, SP, 40);
+  __ StoreToOffset(kStoreWord, S3, SP, 36);
+  __ StoreToOffset(kStoreWord, S2, SP, 32);
+  __ StoreToOffset(kStoreWord, S1, SP, 28);
+  __ StoreToOffset(kStoreWord, S0, SP, 24);
 
   // A0 is the Method* already
   __ Move(A1, S1);  // Pass Thread::Current() in A1
@@ -191,7 +193,8 @@
 
   Label no_native_code_found;
   __ EmitBranch(V0, ZERO, &no_native_code_found, true);
-  __ Jr(V0); // If V0 != 0 tail call method's code
+  __ Move(T9, V0); // Move result into T9
+  __ Jr(T9); // If result != 0, tail call method's code
   __ Bind(&no_native_code_found, false);
   __ Jr(RA); // Return to caller to handle exception
 
diff --git a/src/oat_file.cc b/src/oat_file.cc
index 93ff7a6..1e9d820 100644
--- a/src/oat_file.cc
+++ b/src/oat_file.cc
@@ -49,7 +49,7 @@
                        bool writable) {
   CHECK(!location.empty());
   if (!IsValidOatFilename(location)) {
-    LOG(WARNING) << "Attempting to open dex file with unknown extension '" << location << "'";
+    LOG(WARNING) << "Attempting to open oat file with unknown extension '" << location << "'";
   }
   UniquePtr<OatFile> oat_file(new OatFile(location));
   bool success = oat_file->Map(file, requested_base, reloc, writable);
@@ -102,24 +102,27 @@
                                                  file.Fd(),
                                                  0));
   if (map.get() == NULL) {
-    LOG(WARNING) << "Failed to map oat file " << GetLocation();
+    LOG(WARNING) << "Failed to map oat file from " << file.name() << " for " << GetLocation();
     return false;
   }
   CHECK(requested_base == 0 || requested_base == map->Begin())
-      << GetLocation() << " " << reinterpret_cast<void*>(map->Begin());
-  DCHECK_EQ(0, memcmp(&oat_header, map->Begin(), sizeof(OatHeader))) << GetLocation();
+      << file.name() << " for " << GetLocation() << " " << reinterpret_cast<void*>(map->Begin());
+  DCHECK_EQ(0, memcmp(&oat_header, map->Begin(), sizeof(OatHeader)))
+      << file.name() << " for " << GetLocation();
 
   off_t code_offset = oat_header.GetExecutableOffset();
   if (code_offset < file.Length()) {
     byte* code_address = map->Begin() + code_offset;
     size_t code_length = file.Length() - code_offset;
     if (mprotect(code_address, code_length, prot | PROT_EXEC) != 0) {
-      PLOG(ERROR) << "Failed to make oat code executable in " << GetLocation();
+      PLOG(ERROR) << "Failed to make oat code executable in "
+                  << file.name() << " for " << GetLocation();
       return false;
     }
   } else {
     // its possible to have no code if all the methods were abstract, native, etc
-    DCHECK_EQ(code_offset, RoundUp(file.Length(), kPageSize)) << GetLocation();
+    DCHECK_EQ(code_offset, RoundUp(file.Length(), kPageSize))
+        << file.name() << " for " << GetLocation();
   }
 
   const byte* oat = map->Begin();
@@ -132,37 +135,40 @@
     << "+" << sizeof(OatHeader)
     << "+" << oat_header.GetImageFileLocationSize()
     << "<=" << reinterpret_cast<void*>(map->End())
-    << " " << GetLocation();
+    << " " << file.name() << " for " << GetLocation();
   for (size_t i = 0; i < oat_header.GetDexFileCount(); i++) {
     size_t dex_file_location_size = *reinterpret_cast<const uint32_t*>(oat);
-    CHECK_GT(dex_file_location_size, 0U) << GetLocation();
+    CHECK_GT(dex_file_location_size, 0U) << file.name() << " for " << GetLocation();
     oat += sizeof(dex_file_location_size);
-    CHECK_LT(oat, map->End()) << GetLocation();
+    CHECK_LT(oat, map->End()) << file.name() << " for " << GetLocation();
 
     const char* dex_file_location_data = reinterpret_cast<const char*>(oat);
     oat += dex_file_location_size;
-    CHECK_LT(oat, map->End()) << GetLocation();
+    CHECK_LT(oat, map->End()) << file.name() << " for " << GetLocation();
 
     std::string dex_file_location(dex_file_location_data, dex_file_location_size);
 
     uint32_t dex_file_checksum = *reinterpret_cast<const uint32_t*>(oat);
     oat += sizeof(dex_file_checksum);
-    CHECK_LT(oat, map->End()) << GetLocation();
+    CHECK_LT(oat, map->End()) << file.name() << " for " << GetLocation();
 
     uint32_t dex_file_offset = *reinterpret_cast<const uint32_t*>(oat);
-    CHECK_GT(dex_file_offset, 0U) << GetLocation();
-    CHECK_LT(dex_file_offset, static_cast<uint32_t>(file.Length())) << GetLocation();
+    CHECK_GT(dex_file_offset, 0U) << file.name() << " for " << GetLocation();
+    CHECK_LT(dex_file_offset, static_cast<uint32_t>(file.Length()))
+        << file.name() << " for " << GetLocation();
     oat += sizeof(dex_file_offset);
-    CHECK_LT(oat, map->End()) << GetLocation();
+    CHECK_LT(oat, map->End()) << file.name() << " for " << GetLocation();
 
     uint8_t* dex_file_pointer = map->Begin() + dex_file_offset;
-    CHECK(DexFile::IsMagicValid(dex_file_pointer)) << GetLocation() << " " << dex_file_pointer;
-    CHECK(DexFile::IsVersionValid(dex_file_pointer)) << GetLocation() << " "  << dex_file_pointer;
+    CHECK(DexFile::IsMagicValid(dex_file_pointer))
+        << file.name() << " for " << GetLocation() << " " << dex_file_pointer;
+    CHECK(DexFile::IsVersionValid(dex_file_pointer))
+        << file.name() << " for " << GetLocation() << " "  << dex_file_pointer;
     const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer);
     const uint32_t* methods_offsets_pointer = reinterpret_cast<const uint32_t*>(oat);
 
     oat += (sizeof(*methods_offsets_pointer) * header->class_defs_size_);
-    CHECK_LE(oat, map->End()) << GetLocation();
+    CHECK_LE(oat, map->End()) << file.name() << " for " << GetLocation();
 
     oat_dex_files_.Put(dex_file_location, new OatDexFile(this,
                                                          dex_file_location,
@@ -230,7 +236,8 @@
 
 const DexFile* OatFile::OatDexFile::OpenDexFile() const {
   size_t length = reinterpret_cast<const DexFile::Header*>(dex_file_pointer_)->file_size_;
-  return DexFile::Open(dex_file_pointer_, length, dex_file_location_, dex_file_location_checksum_);
+  return DexFile::Open(dex_file_pointer_, length, dex_file_location_,
+                       dex_file_location_checksum_);
 }
 
 const OatFile::OatClass* OatFile::OatDexFile::GetOatClass(uint32_t class_def_index) const {
diff --git a/src/oat_test.cc b/src/oat_test.cc
index ae4aae2..64c502d 100644
--- a/src/oat_test.cc
+++ b/src/oat_test.cc
@@ -75,6 +75,7 @@
                                    class_loader,
                                    class_linker->GetBootClassPath(),
                                    42U,
+                                   4096U,
                                    "lue.art",
                                    *compiler_.get());
   ASSERT_TRUE(success);
@@ -88,8 +89,10 @@
                                             OatFile::kRelocNone));
   ASSERT_TRUE(oat_file.get() != NULL);
   const OatHeader& oat_header = oat_file->GetOatHeader();
+  ASSERT_TRUE(oat_header.IsValid());
   ASSERT_EQ(1U, oat_header.GetDexFileCount());
-  ASSERT_EQ(42U, oat_header.GetImageFileLocationChecksum());
+  ASSERT_EQ(42U, oat_header.GetImageFileLocationOatChecksum());
+  ASSERT_EQ(4096U, oat_header.GetImageFileLocationOatBegin());
   ASSERT_EQ("lue.art", oat_header.GetImageFileLocation());
 
   const DexFile* dex_file = java_lang_dex_file_;
@@ -124,8 +127,33 @@
 TEST_F(OatTest, OatHeaderSizeCheck) {
   // If this test is failing and you have to update these constants,
   // it is time to update OatHeader::kOatVersion
-  EXPECT_EQ(32U, sizeof(OatHeader));
+  EXPECT_EQ(36U, sizeof(OatHeader));
+#if !defined(ART_USE_LLVM_COMPILER)
   EXPECT_EQ(32U, sizeof(OatMethodOffsets));
+#else
+  // ART-LLVM has a extra 4 bytes field: proxy_stub_offset_
+  EXPECT_EQ(36U, sizeof(OatMethodOffsets));
+#endif
+}
+
+TEST_F(OatTest, OatHeaderIsValid) {
+    InstructionSet instruction_set = kX86;
+    std::vector<const DexFile*> dex_files;
+    uint32_t image_file_location_oat_checksum = 0;
+    uint32_t image_file_location_oat_begin = 0;
+    const std::string image_file_location;
+    OatHeader oat_header(instruction_set,
+                         &dex_files,
+                         image_file_location_oat_checksum,
+                         image_file_location_oat_begin,
+                         image_file_location);
+    ASSERT_TRUE(oat_header.IsValid());
+
+    char* magic = const_cast<char*>(oat_header.GetMagic());
+    strcpy(magic, "");  // bad magic
+    ASSERT_FALSE(oat_header.IsValid());
+    strcpy(magic, "oat\n000"); // bad version
+    ASSERT_FALSE(oat_header.IsValid());
 }
 
 }  // namespace art
diff --git a/src/oat_writer.cc b/src/oat_writer.cc
index 5e12299..e26e3cc 100644
--- a/src/oat_writer.cc
+++ b/src/oat_writer.cc
@@ -33,11 +33,13 @@
 bool OatWriter::Create(File* file,
                        jobject class_loader,
                        const std::vector<const DexFile*>& dex_files,
-                       uint32_t image_file_location_checksum,
+                       uint32_t image_file_location_oat_checksum,
+                       uint32_t image_file_location_oat_begin,
                        const std::string& image_file_location,
                        const Compiler& compiler) {
   OatWriter oat_writer(dex_files,
-                       image_file_location_checksum,
+                       image_file_location_oat_checksum,
+                       image_file_location_oat_begin,
                        image_file_location,
                        class_loader,
                        compiler);
@@ -45,13 +47,15 @@
 }
 
 OatWriter::OatWriter(const std::vector<const DexFile*>& dex_files,
-                     uint32_t image_file_location_checksum,
+                     uint32_t image_file_location_oat_checksum,
+                     uint32_t image_file_location_oat_begin,
                      const std::string& image_file_location,
                      jobject class_loader,
                      const Compiler& compiler) {
   compiler_ = &compiler;
   class_loader_ = class_loader;
-  image_file_location_checksum_ = image_file_location_checksum;
+  image_file_location_oat_checksum_ = image_file_location_oat_checksum;
+  image_file_location_oat_begin_ = image_file_location_oat_begin;
   image_file_location_ = image_file_location;
   dex_files_ = &dex_files;
   oat_header_ = NULL;
@@ -77,7 +81,8 @@
   // create the OatHeader
   oat_header_ = new OatHeader(compiler_->GetInstructionSet(),
                               dex_files_,
-                              image_file_location_checksum_,
+                              image_file_location_oat_checksum_,
+                              image_file_location_oat_begin_,
                               image_file_location_);
   size_t offset = sizeof(*oat_header_);
   offset += image_file_location_.size();
@@ -353,7 +358,7 @@
   }
 
 #if defined(ART_USE_LLVM_COMPILER)
-  if (type == kStatic) {
+  if (type != kStatic) {
     const CompiledInvokeStub* compiled_proxy_stub = compiler_->FindProxyStub(shorty);
     if (compiled_proxy_stub != NULL) {
       offset = CompiledMethod::AlignCode(offset, compiler_->GetInstructionSet());
@@ -733,7 +738,7 @@
   }
 
 #if defined(ART_USE_LLVM_COMPILER)
-  if (is_static) {
+  if (!is_static) {
     const CompiledInvokeStub* compiled_proxy_stub = compiler_->FindProxyStub(shorty);
     if (compiled_proxy_stub != NULL) {
       uint32_t aligned_code_offset = CompiledMethod::AlignCode(code_offset,
diff --git a/src/oat_writer.h b/src/oat_writer.h
index fd8e2b2..09db96b 100644
--- a/src/oat_writer.h
+++ b/src/oat_writer.h
@@ -66,14 +66,16 @@
   static bool Create(File* file,
                      jobject class_loader,
                      const std::vector<const DexFile*>& dex_files,
-                     uint32_t image_file_location_checksum,
+                     uint32_t image_file_location_oat_checksum,
+                     uint32_t image_file_location_oat_begin,
                      const std::string& image_file_location,
                      const Compiler& compiler)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
  private:
   OatWriter(const std::vector<const DexFile*>& dex_files,
-            uint32_t image_file_location_checksum,
+            uint32_t image_file_location_oat_checksum,
+            uint32_t image_file_location_oat_begin,
             const std::string& image_file_location,
             jobject class_loader,
             const Compiler& compiler) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -156,8 +158,9 @@
   // note OatFile does not take ownership of the DexFiles
   const std::vector<const DexFile*>* dex_files_;
 
-  // dependency on the image
-  uint32_t image_file_location_checksum_;
+  // dependencies on the image.
+  uint32_t image_file_location_oat_checksum_;
+  uint32_t image_file_location_oat_begin_;
   std::string image_file_location_;
 
   // data to write
diff --git a/src/oatdump.cc b/src/oatdump.cc
index b4ba3df..6c7e2ef 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -48,7 +48,7 @@
           "\n");
   fprintf(stderr,
           "  --oat-file=<file.oat>: specifies an input oat filename.\n"
-          "      Example: --image=/system/framework/boot.oat\n"
+          "      Example: --oat-file=/system/framework/boot.oat\n"
           "\n");
   fprintf(stderr,
           "  --image=<file.art>: specifies an input image filename.\n"
@@ -113,8 +113,11 @@
     os << "EXECUTABLE OFFSET:\n";
     os << StringPrintf("0x%08x\n\n", oat_header.GetExecutableOffset());
 
-    os << "IMAGE FILE LOCATION CHECKSUM:\n";
-    os << StringPrintf("0x%08x\n\n", oat_header.GetImageFileLocationChecksum());
+    os << "IMAGE FILE LOCATION OAT CHECKSUM:\n";
+    os << StringPrintf("0x%08x\n\n", oat_header.GetImageFileLocationOatChecksum());
+
+    os << "IMAGE FILE LOCATION OAT BEGIN:\n";
+    os << StringPrintf("0x%08x\n\n", oat_header.GetImageFileLocationOatBegin());
 
     os << "IMAGE FILE LOCATION:\n";
     const std::string image_file_location(oat_header.GetImageFileLocation());
diff --git a/src/runtime.cc b/src/runtime.cc
index f93d687..3a5c41c 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -993,10 +993,17 @@
   thread_list_->Unregister(self);
 }
 
-void Runtime::VisitRoots(Heap::RootVisitor* visitor, void* arg) const {
+void Runtime::VisitConcurrentRoots(Heap::RootVisitor* visitor, void* arg) {
+  if (intern_table_->IsDirty()) {
+    intern_table_->VisitRoots(visitor, arg);
+  }
+  if (class_linker_->IsDirty()) {
+    class_linker_->VisitRoots(visitor, arg);
+  }
+}
+
+void Runtime::VisitNonConcurrentRoots(Heap::RootVisitor* visitor, void* arg) {
   Dbg::VisitRoots(visitor, arg);
-  class_linker_->VisitRoots(visitor, arg);
-  intern_table_->VisitRoots(visitor, arg);
   java_vm_->VisitRoots(visitor, arg);
   thread_list_->VisitRoots(visitor, arg);
   if (pre_allocated_OutOfMemoryError_ != NULL) {
@@ -1013,6 +1020,16 @@
   }
 }
 
+void Runtime::DirtyRoots() {
+  intern_table_->Dirty();
+  class_linker_->Dirty();
+}
+
+void Runtime::VisitRoots(Heap::RootVisitor* visitor, void* arg) {
+  VisitConcurrentRoots(visitor, arg);
+  VisitNonConcurrentRoots(visitor, arg);
+}
+
 void Runtime::SetJniDlsymLookupStub(ByteArray* jni_stub_array) {
   CHECK(jni_stub_array != NULL)  << " jni_stub_array=" << jni_stub_array;
   CHECK(jni_stub_array_ == NULL || jni_stub_array_ == jni_stub_array)
@@ -1088,7 +1105,7 @@
     uint32_t core_spills = ref_spills | (type == kRefsAndArgs ? arg_spills : 0) |
                            (type == kSaveAll ? all_spills : 0) | (1 << art::mips::RA);
     size_t frame_size = RoundUp((__builtin_popcount(core_spills) /* gprs */ +
-                                 (type == kRefsAndArgs ? 0 : 3) /* always reserve arg space */ +
+                                 (type == kRefsAndArgs ? 0 : 5) /* reserve arg space */ +
                                  1 /* Method* */) * kPointerSize, kStackAlignment);
     method->SetFrameSizeInBytes(frame_size);
     method->SetCoreSpillMask(core_spills);
diff --git a/src/runtime.h b/src/runtime.h
index a6c662c..44823a0 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -224,9 +224,20 @@
     return "2.0.0";
   }
 
-  void VisitRoots(Heap::RootVisitor* visitor, void* arg) const
+  // Force all the roots which can be marked concurrently to be dirty.
+  void DirtyRoots();
+
+  // Visit all the roots.
+  void VisitRoots(Heap::RootVisitor* visitor, void* arg)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  // Visit all of the roots we can do safely do concurrently.
+  void VisitConcurrentRoots(Heap::RootVisitor* visitor, void* arg);
+
+  // Visit all other roots which must be done with mutators suspended.
+  void VisitNonConcurrentRoots(Heap::RootVisitor* visitor, void* arg)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   bool HasJniDlsymLookupStub() const {
     return jni_stub_array_ != NULL;
   }
diff --git a/src/thread.cc b/src/thread.cc
index 6daeadf..cea919f 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -2013,9 +2013,9 @@
 
 void Thread::VerifyStack() {
   UniquePtr<Context> context(Context::Create());
-  RootCallbackVisitor visitorToCallback(visitor, arg);
+  RootCallbackVisitor visitorToCallback(VerifyObject, Runtime::Current()->GetHeap());
   ReferenceMapVisitor<RootCallbackVisitor> mapper(GetManagedStack(), GetTraceStack(), context.get(),
-                                                  VerifyObject, Runtime::Current()->GetHeap());
+                                                  visitorToCallback);
   mapper.WalkStack();
 }
 #endif