Merge "Convert more of art to Android.bp"
diff --git a/build/Android.common_test.mk b/build/Android.common_test.mk
index 93e310e..6b7dc09 100644
--- a/build/Android.common_test.mk
+++ b/build/Android.common_test.mk
@@ -60,8 +60,8 @@
 # Do you want to test the optimizing compiler with graph coloring register allocation?
 ART_TEST_OPTIMIZING_GRAPH_COLOR ?= $(ART_TEST_FULL)
 
-# Do we want to test a PIC-compiled core image?
-ART_TEST_PIC_IMAGE ?= $(ART_TEST_FULL)
+# Do we want to test a non-PIC-compiled core image?
+ART_TEST_NPIC_IMAGE ?= $(ART_TEST_FULL)
 
 # Do we want to test PIC-compiled tests ("apps")?
 ART_TEST_PIC_TEST ?= $(ART_TEST_FULL)
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index 8a6d52d..9120a32 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -90,16 +90,16 @@
 ART_GTEST_type_lookup_table_test_DEX_DEPS := Lookup
 
 # The elf writer test has dependencies on core.oat.
-ART_GTEST_elf_writer_test_HOST_DEPS := $(HOST_CORE_IMAGE_default_no-pic_64) $(HOST_CORE_IMAGE_default_no-pic_32)
-ART_GTEST_elf_writer_test_TARGET_DEPS := $(TARGET_CORE_IMAGE_default_no-pic_64) $(TARGET_CORE_IMAGE_default_no-pic_32)
+ART_GTEST_elf_writer_test_HOST_DEPS := $(HOST_CORE_IMAGE_optimizing_no-pic_64) $(HOST_CORE_IMAGE_optimizing_no-pic_32)
+ART_GTEST_elf_writer_test_TARGET_DEPS := $(TARGET_CORE_IMAGE_optimizing_no-pic_64) $(TARGET_CORE_IMAGE_optimizing_no-pic_32)
 
 ART_GTEST_dex2oat_environment_tests_HOST_DEPS := \
-  $(HOST_CORE_IMAGE_default_no-pic_64) \
-  $(HOST_CORE_IMAGE_default_no-pic_32) \
+  $(HOST_CORE_IMAGE_optimizing_no-pic_64) \
+  $(HOST_CORE_IMAGE_optimizing_no-pic_32) \
   $(HOST_OUT_EXECUTABLES)/patchoatd
 ART_GTEST_dex2oat_environment_tests_TARGET_DEPS := \
-  $(TARGET_CORE_IMAGE_default_no-pic_64) \
-  $(TARGET_CORE_IMAGE_default_no-pic_32) \
+  $(TARGET_CORE_IMAGE_optimizing_no-pic_64) \
+  $(TARGET_CORE_IMAGE_optimizing_no-pic_32) \
   $(TARGET_OUT_EXECUTABLES)/patchoatd
 
 ART_GTEST_oat_file_assistant_test_HOST_DEPS := \
@@ -114,62 +114,62 @@
   $(ART_GTEST_dex2oat_environment_tests_TARGET_DEPS)
 
 # TODO: document why this is needed.
-ART_GTEST_proxy_test_HOST_DEPS := $(HOST_CORE_IMAGE_default_no-pic_64) $(HOST_CORE_IMAGE_default_no-pic_32)
+ART_GTEST_proxy_test_HOST_DEPS := $(HOST_CORE_IMAGE_optimizing_no-pic_64) $(HOST_CORE_IMAGE_optimizing_no-pic_32)
 
 # The dexdump test requires an image and the dexdump utility.
 # TODO: rename into dexdump when migration completes
 ART_GTEST_dexdump_test_HOST_DEPS := \
-  $(HOST_CORE_IMAGE_default_no-pic_64) \
-  $(HOST_CORE_IMAGE_default_no-pic_32) \
+  $(HOST_CORE_IMAGE_optimizing_no-pic_64) \
+  $(HOST_CORE_IMAGE_optimizing_no-pic_32) \
   $(HOST_OUT_EXECUTABLES)/dexdump2
 ART_GTEST_dexdump_test_TARGET_DEPS := \
-  $(TARGET_CORE_IMAGE_default_no-pic_64) \
-  $(TARGET_CORE_IMAGE_default_no-pic_32) \
+  $(TARGET_CORE_IMAGE_optimizing_no-pic_64) \
+  $(TARGET_CORE_IMAGE_optimizing_no-pic_32) \
   dexdump2
 
 # The dexlayout test requires an image and the dexlayout utility.
 # TODO: rename into dexdump when migration completes
 ART_GTEST_dexlayout_test_HOST_DEPS := \
-  $(HOST_CORE_IMAGE_default_no-pic_64) \
-  $(HOST_CORE_IMAGE_default_no-pic_32) \
+  $(HOST_CORE_IMAGE_optimizing_no-pic_64) \
+  $(HOST_CORE_IMAGE_optimizing_no-pic_32) \
   $(HOST_OUT_EXECUTABLES)/dexlayout \
   $(HOST_OUT_EXECUTABLES)/dexdump2
 ART_GTEST_dexlayout_test_TARGET_DEPS := \
-  $(TARGET_CORE_IMAGE_default_no-pic_64) \
-  $(TARGET_CORE_IMAGE_default_no-pic_32) \
+  $(TARGET_CORE_IMAGE_optimizing_no-pic_64) \
+  $(TARGET_CORE_IMAGE_optimizing_no-pic_32) \
   dexlayout \
   dexdump2
 
 # The dexlist test requires an image and the dexlist utility.
 ART_GTEST_dexlist_test_HOST_DEPS := \
-  $(HOST_CORE_IMAGE_default_no-pic_64) \
-  $(HOST_CORE_IMAGE_default_no-pic_32) \
+  $(HOST_CORE_IMAGE_optimizing_no-pic_64) \
+  $(HOST_CORE_IMAGE_optimizing_no-pic_32) \
   $(HOST_OUT_EXECUTABLES)/dexlist
 ART_GTEST_dexlist_test_TARGET_DEPS := \
-  $(TARGET_CORE_IMAGE_default_no-pic_64) \
-  $(TARGET_CORE_IMAGE_default_no-pic_32) \
+  $(TARGET_CORE_IMAGE_optimizing_no-pic_64) \
+  $(TARGET_CORE_IMAGE_optimizing_no-pic_32) \
   dexlist
 
 # The imgdiag test has dependencies on core.oat since it needs to load it during the test.
 # For the host, also add the installed tool (in the base size, that should suffice). For the
 # target, just the module is fine, the sync will happen late enough.
 ART_GTEST_imgdiag_test_HOST_DEPS := \
-  $(HOST_CORE_IMAGE_default_no-pic_64) \
-  $(HOST_CORE_IMAGE_default_no-pic_32) \
+  $(HOST_CORE_IMAGE_optimizing_no-pic_64) \
+  $(HOST_CORE_IMAGE_optimizing_no-pic_32) \
   $(HOST_OUT_EXECUTABLES)/imgdiagd
 ART_GTEST_imgdiag_test_TARGET_DEPS := \
-  $(TARGET_CORE_IMAGE_default_no-pic_64) \
-  $(TARGET_CORE_IMAGE_default_no-pic_32) \
+  $(TARGET_CORE_IMAGE_optimizing_no-pic_64) \
+  $(TARGET_CORE_IMAGE_optimizing_no-pic_32) \
   imgdiagd
 
 # Oatdump test requires an image and oatfile to dump.
 ART_GTEST_oatdump_test_HOST_DEPS := \
-  $(HOST_CORE_IMAGE_default_no-pic_64) \
-  $(HOST_CORE_IMAGE_default_no-pic_32) \
+  $(HOST_CORE_IMAGE_optimizing_no-pic_64) \
+  $(HOST_CORE_IMAGE_optimizing_no-pic_32) \
   $(HOST_OUT_EXECUTABLES)/oatdumpd
 ART_GTEST_oatdump_test_TARGET_DEPS := \
-  $(TARGET_CORE_IMAGE_default_no-pic_64) \
-  $(TARGET_CORE_IMAGE_default_no-pic_32) \
+  $(TARGET_CORE_IMAGE_optimizing_no-pic_64) \
+  $(TARGET_CORE_IMAGE_optimizing_no-pic_32) \
   oatdump
 
 # Profile assistant tests requires profman utility.
@@ -238,6 +238,7 @@
   runtime/gc/space/rosalloc_space_static_test.cc \
   runtime/gc/space/rosalloc_space_random_test.cc \
   runtime/gc/space/space_create_test.cc \
+  runtime/gc/system_weak_test.cc \
   runtime/gc/task_processor_test.cc \
   runtime/gtest_test.cc \
   runtime/handle_scope_test.cc \
@@ -694,7 +695,7 @@
     LOCAL_CLANG := $$(ART_HOST_CLANG)
     LOCAL_CFLAGS += $$(ART_HOST_CFLAGS) $$(ART_HOST_DEBUG_CFLAGS)
     LOCAL_ASFLAGS += $$(ART_HOST_ASFLAGS) $$(ART_HOST_DEBUG_ASFLAGS)
-    LOCAL_SHARED_LIBRARIES += libicuuc-host libicui18n-host libnativehelper libziparchive libz-host libvixld-arm libvixld-arm64
+    LOCAL_SHARED_LIBRARIES += libicuuc libicui18n libnativehelper libziparchive libz-host libvixld-arm libvixld-arm64
     LOCAL_LDLIBS := -lpthread -ldl
     LOCAL_IS_HOST_MODULE := true
     LOCAL_MULTILIB := both
diff --git a/build/Android.oat.mk b/build/Android.oat.mk
index 884f698..c4887e6 100644
--- a/build/Android.oat.mk
+++ b/build/Android.oat.mk
@@ -37,7 +37,7 @@
 endif
 
 # Use dex2oat debug version for better error reporting
-# $(1): compiler - default, optimizing, jit, interpreter or interpreter-access-checks.
+# $(1): compiler - optimizing, interpreter or interpreter-access-checks.
 # $(2): pic/no-pic
 # $(3): 2ND_ or undefined, 2ND_ for 32-bit host builds.
 # $(4): wrapper, e.g., valgrind.
@@ -53,13 +53,9 @@
   core_pic_infix :=
   core_dex2oat_dependency := $(DEX2OAT_DEPENDENCY)
 
-  ifeq ($(1),default)
-    core_compile_options += --compiler-backend=Quick
-  endif
   ifeq ($(1),optimizing)
     core_compile_options += --compiler-backend=Optimizing
     core_dex2oat_dependency := $(DEX2OAT)
-    core_infix := -optimizing
   endif
   ifeq ($(1),interpreter)
     core_compile_options += --compiler-filter=interpret-only
@@ -69,24 +65,16 @@
     core_compile_options += --compiler-filter=verify-at-runtime --runtime-arg -Xverify:softfail
     core_infix := -interp-ac
   endif
-  ifeq ($(1),jit)
-    core_compile_options += --compiler-filter=verify-at-runtime
-    core_infix := -jit
-  endif
-  ifeq ($(1),default)
-    # Default has no infix, no compile options.
-  endif
-  ifneq ($(filter-out default interpreter interp-ac jit optimizing,$(1)),)
+  ifneq ($(filter-out interpreter interp-ac optimizing,$(1)),)
     #Technically this test is not precise, but hopefully good enough.
-    $$(error found $(1) expected default, interpreter, interpreter-access-checks, jit or optimizing)
+    $$(error found $(1) expected interpreter, interpreter-access-checks, or optimizing)
   endif
 
   ifeq ($(2),pic)
     core_compile_options += --compile-pic
-    core_pic_infix := -pic
   endif
   ifeq ($(2),no-pic)
-    # No change for non-pic
+    core_pic_infix := -npic
   endif
   ifneq ($(filter-out pic no-pic,$(2)),)
     # Technically this test is not precise, but hopefully good enough.
@@ -148,7 +136,7 @@
   core_pic_infix :=
 endef  # create-core-oat-host-rules
 
-# $(1): compiler - default, optimizing, jit, interpreter or interpreter-access-checks.
+# $(1): compiler - optimizing, interpreter or interpreter-access-checks.
 # $(2): wrapper.
 # $(3): dex2oat suffix.
 # $(4): multi-image.
@@ -162,24 +150,18 @@
   endif
 endef
 
-$(eval $(call create-core-oat-host-rule-combination,default,,,false))
 $(eval $(call create-core-oat-host-rule-combination,optimizing,,,false))
 $(eval $(call create-core-oat-host-rule-combination,interpreter,,,false))
 $(eval $(call create-core-oat-host-rule-combination,interp-ac,,,false))
-$(eval $(call create-core-oat-host-rule-combination,jit,,,false))
-$(eval $(call create-core-oat-host-rule-combination,default,,,true))
 $(eval $(call create-core-oat-host-rule-combination,optimizing,,,true))
 $(eval $(call create-core-oat-host-rule-combination,interpreter,,,true))
 $(eval $(call create-core-oat-host-rule-combination,interp-ac,,,true))
-$(eval $(call create-core-oat-host-rule-combination,jit,,,true))
 
 valgrindHOST_CORE_IMG_OUTS :=
 valgrindHOST_CORE_OAT_OUTS :=
-$(eval $(call create-core-oat-host-rule-combination,default,valgrind,32,false))
 $(eval $(call create-core-oat-host-rule-combination,optimizing,valgrind,32,false))
 $(eval $(call create-core-oat-host-rule-combination,interpreter,valgrind,32,false))
 $(eval $(call create-core-oat-host-rule-combination,interp-ac,valgrind,32,false))
-$(eval $(call create-core-oat-host-rule-combination,jit,valgrind,32,false))
 
 valgrind-test-art-host-dex2oat-host: $(valgrindHOST_CORE_IMG_OUTS)
 
@@ -193,15 +175,11 @@
   core_pic_infix :=
   core_dex2oat_dependency := $(DEX2OAT_DEPENDENCY)
 
-  ifeq ($(1),default)
-    core_compile_options += --compiler-backend=Quick
-  endif
   ifeq ($(1),optimizing)
     core_compile_options += --compiler-backend=Optimizing
     # With the optimizing compiler, we want to rerun dex2oat whenever there is
     # a dex2oat change to catch regressions early.
     core_dex2oat_dependency := $(DEX2OAT)
-    core_infix := -optimizing
   endif
   ifeq ($(1),interpreter)
     core_compile_options += --compiler-filter=interpret-only
@@ -211,24 +189,16 @@
     core_compile_options += --compiler-filter=verify-at-runtime --runtime-arg -Xverify:softfail
     core_infix := -interp-ac
   endif
-  ifeq ($(1),jit)
-    core_compile_options += --compiler-filter=verify-at-runtime
-    core_infix := -jit
-  endif
-  ifeq ($(1),default)
-    # Default has no infix, no compile options.
-  endif
-  ifneq ($(filter-out default interpreter interp-ac jit optimizing,$(1)),)
+  ifneq ($(filter-out interpreter interp-ac optimizing,$(1)),)
     # Technically this test is not precise, but hopefully good enough.
-    $$(error found $(1) expected default, interpreter, interpreter-access-checks, jit or optimizing)
+    $$(error found $(1) expected interpreter, interpreter-access-checks, or optimizing)
   endif
 
   ifeq ($(2),pic)
     core_compile_options += --compile-pic
-    core_pic_infix := -pic
   endif
   ifeq ($(2),no-pic)
-    # No change for non-pic
+    core_pic_infix := -npic
   endif
   ifneq ($(filter-out pic no-pic,$(2)),)
     #Technically this test is not precise, but hopefully good enough.
@@ -283,7 +253,7 @@
   core_pic_infix :=
 endef  # create-core-oat-target-rules
 
-# $(1): compiler - default, optimizing, jit, interpreter or interpreter-access-checks.
+# $(1): compiler - optimizing, interpreter or interpreter-access-checks.
 # $(2): wrapper.
 # $(3): dex2oat suffix.
 define create-core-oat-target-rule-combination
@@ -296,19 +266,15 @@
   endif
 endef
 
-$(eval $(call create-core-oat-target-rule-combination,default,,))
 $(eval $(call create-core-oat-target-rule-combination,optimizing,,))
 $(eval $(call create-core-oat-target-rule-combination,interpreter,,))
 $(eval $(call create-core-oat-target-rule-combination,interp-ac,,))
-$(eval $(call create-core-oat-target-rule-combination,jit,,))
 
 valgrindTARGET_CORE_IMG_OUTS :=
 valgrindTARGET_CORE_OAT_OUTS :=
-$(eval $(call create-core-oat-target-rule-combination,default,valgrind,32))
 $(eval $(call create-core-oat-target-rule-combination,optimizing,valgrind,32))
 $(eval $(call create-core-oat-target-rule-combination,interpreter,valgrind,32))
 $(eval $(call create-core-oat-target-rule-combination,interp-ac,valgrind,32))
-$(eval $(call create-core-oat-target-rule-combination,jit,valgrind,32))
 
 valgrind-test-art-host-dex2oat-target: $(valgrindTARGET_CORE_IMG_OUTS)
 
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index daac7fb..53e068e 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -72,6 +72,7 @@
 #include "utils/swap_space.h"
 #include "verifier/method_verifier.h"
 #include "verifier/method_verifier-inl.h"
+#include "verifier/verifier_log_mode.h"
 
 namespace art {
 
@@ -2258,7 +2259,7 @@
 
 class VerifyClassVisitor : public CompilationVisitor {
  public:
-  VerifyClassVisitor(const ParallelCompilationManager* manager, LogSeverity log_level)
+  VerifyClassVisitor(const ParallelCompilationManager* manager, verifier::HardFailLogMode log_level)
      : manager_(manager), log_level_(log_level) {}
 
   virtual void Visit(size_t class_def_index) REQUIRES(!Locks::mutator_lock_) OVERRIDE {
@@ -2329,7 +2330,7 @@
 
  private:
   const ParallelCompilationManager* const manager_;
-  const LogSeverity log_level_;
+  const verifier::HardFailLogMode log_level_;
 };
 
 void CompilerDriver::VerifyDexFile(jobject class_loader,
@@ -2342,9 +2343,9 @@
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   ParallelCompilationManager context(class_linker, class_loader, this, &dex_file, dex_files,
                                      thread_pool);
-  LogSeverity log_level = GetCompilerOptions().AbortOnHardVerifierFailure()
-                              ? LogSeverity::INTERNAL_FATAL
-                              : LogSeverity::WARNING;
+  verifier::HardFailLogMode log_level = GetCompilerOptions().AbortOnHardVerifierFailure()
+                              ? verifier::HardFailLogMode::kLogInternalFatal
+                              : verifier::HardFailLogMode::kLogWarning;
   VerifyClassVisitor visitor(&context, log_level);
   context.ForAll(0, dex_file.NumClassDefs(), &visitor, thread_count);
 }
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index ac7d5fe..2087888 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -1081,6 +1081,13 @@
   }
 }
 
+bool CodeGenerator::IsImplicitNullCheckAllowed(HNullCheck* null_check) const {
+  return compiler_options_.GetImplicitNullChecks() &&
+         // Null checks which might throw into a catch block need to save live
+         // registers and therefore cannot be done implicitly.
+         !null_check->CanThrowIntoCatchBlock();
+}
+
 bool CodeGenerator::CanMoveNullCheckToUser(HNullCheck* null_check) {
   HInstruction* first_next_not_move = null_check->GetNextDisregardingMoves();
 
@@ -1089,10 +1096,6 @@
 }
 
 void CodeGenerator::MaybeRecordImplicitNullCheck(HInstruction* instr) {
-  if (!compiler_options_.GetImplicitNullChecks()) {
-    return;
-  }
-
   // If we are from a static path don't record the pc as we can't throw NPE.
   // NB: having the checks here makes the code much less verbose in the arch
   // specific code generators.
@@ -1111,31 +1114,16 @@
   // and needs to record the pc.
   if (first_prev_not_move != nullptr && first_prev_not_move->IsNullCheck()) {
     HNullCheck* null_check = first_prev_not_move->AsNullCheck();
-    // TODO: The parallel moves modify the environment. Their changes need to be
-    // reverted otherwise the stack maps at the throw point will not be correct.
-    RecordPcInfo(null_check, null_check->GetDexPc());
+    if (IsImplicitNullCheckAllowed(null_check)) {
+      // TODO: The parallel moves modify the environment. Their changes need to be
+      // reverted otherwise the stack maps at the throw point will not be correct.
+      RecordPcInfo(null_check, null_check->GetDexPc());
+    }
   }
 }
 
-LocationSummary* CodeGenerator::CreateNullCheckLocations(HNullCheck* null_check) {
-  // Note: Using kNoCall allows the method to be treated as leaf (and eliminate the
-  // HSuspendCheck from entry block). However, it will still get a valid stack frame
-  // because the HNullCheck needs an environment.
-  LocationSummary::CallKind call_kind = LocationSummary::kNoCall;
-  // When throwing from a try block, we may need to retrieve dalvik registers from
-  // physical registers. For implicit null checks, this is done by using kSaveEverything
-  // runtime method but for explicit null checks we need to save live registers.
-  if (!compiler_options_.GetImplicitNullChecks() && null_check->CanThrowIntoCatchBlock()) {
-    call_kind = LocationSummary::kCallOnSlowPath;
-  }
-  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(null_check, call_kind);
-  locations->SetInAt(0, Location::RequiresRegister());
-  DCHECK(!null_check->HasUses());
-  return locations;
-}
-
 void CodeGenerator::GenerateNullCheck(HNullCheck* instruction) {
-  if (compiler_options_.GetImplicitNullChecks()) {
+  if (IsImplicitNullCheckAllowed(instruction)) {
     MaybeRecordStat(kImplicitNullCheckGenerated);
     GenerateImplicitNullCheck(instruction);
   } else {
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index b4d4b9b..0c60a98 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -313,7 +313,6 @@
 
   bool CanMoveNullCheckToUser(HNullCheck* null_check);
   void MaybeRecordImplicitNullCheck(HInstruction* instruction);
-  LocationSummary* CreateNullCheckLocations(HNullCheck* null_check);
   void GenerateNullCheck(HNullCheck* null_check);
   virtual void GenerateImplicitNullCheck(HNullCheck* null_check) = 0;
   virtual void GenerateExplicitNullCheck(HNullCheck* null_check) = 0;
@@ -323,6 +322,12 @@
   // TODO: Replace with a catch-entering instruction that records the environment.
   void RecordCatchBlockInfo();
 
+  // Returns true if implicit null checks are allowed in the compiler options
+  // and if the null check is not inside a try block. We currently cannot do
+  // implicit null checks in that case because we need the NullCheckSlowPath to
+  // save live registers, which may be needed by the runtime to set catch phis.
+  bool IsImplicitNullCheckAllowed(HNullCheck* null_check) const;
+
   // TODO: Avoid creating the `std::unique_ptr` here.
   void AddSlowPath(SlowPathCode* slow_path) {
     slow_paths_.push_back(std::unique_ptr<SlowPathCode>(slow_path));
@@ -708,8 +713,6 @@
   bool is_leaf_;
 
   // Whether an instruction in the graph accesses the current method.
-  // TODO: Rename: this actually indicates that some instruction in the method
-  // needs the environment including a valid stack frame.
   bool requires_current_method_;
 
   friend class OptimizingCFITest;
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 4c41ac8..3cc2598f 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -4251,7 +4251,14 @@
 }
 
 void LocationsBuilderARM::VisitNullCheck(HNullCheck* instruction) {
-  codegen_->CreateNullCheckLocations(instruction);
+  LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
+      ? LocationSummary::kCallOnSlowPath
+      : LocationSummary::kNoCall;
+  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+  locations->SetInAt(0, Location::RequiresRegister());
+  if (instruction->HasUses()) {
+    locations->SetOut(Location::SameAsFirstInput());
+  }
 }
 
 void CodeGeneratorARM::GenerateImplicitNullCheck(HNullCheck* instruction) {
@@ -5738,7 +5745,6 @@
   bool throws_into_catch = instruction->CanThrowIntoCatchBlock();
 
   TypeCheckKind type_check_kind = instruction->GetTypeCheckKind();
-  bool baker_read_barrier_slow_path = false;
   switch (type_check_kind) {
     case TypeCheckKind::kExactCheck:
     case TypeCheckKind::kAbstractClassCheck:
@@ -5747,7 +5753,6 @@
       call_kind = (throws_into_catch || kEmitCompilerReadBarrier) ?
           LocationSummary::kCallOnSlowPath :
           LocationSummary::kNoCall;  // In fact, call on a fatal (non-returning) slow path.
-      baker_read_barrier_slow_path = kUseBakerReadBarrier && !throws_into_catch;
       break;
     case TypeCheckKind::kArrayCheck:
     case TypeCheckKind::kUnresolvedCheck:
@@ -5757,9 +5762,6 @@
   }
 
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
-  if (baker_read_barrier_slow_path) {
-    locations->SetCustomSlowPathCallerSaves(RegisterSet());  // No caller-save registers.
-  }
   locations->SetInAt(0, Location::RequiresRegister());
   locations->SetInAt(1, Location::RequiresRegister());
   // Note that TypeCheckSlowPathARM uses this "temp" register too.
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index d586f1d..179bf76 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -3250,7 +3250,6 @@
   bool throws_into_catch = instruction->CanThrowIntoCatchBlock();
 
   TypeCheckKind type_check_kind = instruction->GetTypeCheckKind();
-  bool baker_read_barrier_slow_path = false;
   switch (type_check_kind) {
     case TypeCheckKind::kExactCheck:
     case TypeCheckKind::kAbstractClassCheck:
@@ -3259,7 +3258,6 @@
       call_kind = (throws_into_catch || kEmitCompilerReadBarrier) ?
           LocationSummary::kCallOnSlowPath :
           LocationSummary::kNoCall;  // In fact, call on a fatal (non-returning) slow path.
-      baker_read_barrier_slow_path = kUseBakerReadBarrier && !throws_into_catch;
       break;
     case TypeCheckKind::kArrayCheck:
     case TypeCheckKind::kUnresolvedCheck:
@@ -3269,9 +3267,6 @@
   }
 
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
-  if (baker_read_barrier_slow_path) {
-    locations->SetCustomSlowPathCallerSaves(RegisterSet());  // No caller-save registers.
-  }
   locations->SetInAt(0, Location::RequiresRegister());
   locations->SetInAt(1, Location::RequiresRegister());
   // Note that TypeCheckSlowPathARM64 uses this "temp" register too.
@@ -4389,7 +4384,14 @@
 }
 
 void LocationsBuilderARM64::VisitNullCheck(HNullCheck* instruction) {
-  codegen_->CreateNullCheckLocations(instruction);
+  LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
+      ? LocationSummary::kCallOnSlowPath
+      : LocationSummary::kNoCall;
+  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+  locations->SetInAt(0, Location::RequiresRegister());
+  if (instruction->HasUses()) {
+    locations->SetOut(Location::SameAsFirstInput());
+  }
 }
 
 void CodeGeneratorARM64::GenerateImplicitNullCheck(HNullCheck* instruction) {
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index fdfc551..f07f8a0 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -5075,7 +5075,14 @@
 }
 
 void LocationsBuilderMIPS::VisitNullCheck(HNullCheck* instruction) {
-  codegen_->CreateNullCheckLocations(instruction);
+  LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
+      ? LocationSummary::kCallOnSlowPath
+      : LocationSummary::kNoCall;
+  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+  locations->SetInAt(0, Location::RequiresRegister());
+  if (instruction->HasUses()) {
+    locations->SetOut(Location::SameAsFirstInput());
+  }
 }
 
 void CodeGeneratorMIPS::GenerateImplicitNullCheck(HNullCheck* instruction) {
diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc
index 4d87523..664d498 100644
--- a/compiler/optimizing/code_generator_mips64.cc
+++ b/compiler/optimizing/code_generator_mips64.cc
@@ -3461,7 +3461,14 @@
 }
 
 void LocationsBuilderMIPS64::VisitNullCheck(HNullCheck* instruction) {
-  codegen_->CreateNullCheckLocations(instruction);
+  LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
+      ? LocationSummary::kCallOnSlowPath
+      : LocationSummary::kNoCall;
+  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+  locations->SetInAt(0, Location::RequiresRegister());
+  if (instruction->HasUses()) {
+    locations->SetOut(Location::SameAsFirstInput());
+  }
 }
 
 void CodeGeneratorMIPS64::GenerateImplicitNullCheck(HNullCheck* instruction) {
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 64c4754..e18b366 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -4950,10 +4950,16 @@
 }
 
 void LocationsBuilderX86::VisitNullCheck(HNullCheck* instruction) {
-  LocationSummary* locations = codegen_->CreateNullCheckLocations(instruction);
-  if (!codegen_->GetCompilerOptions().GetImplicitNullChecks()) {
-    // Explicit null checks can use any location.
-    locations->SetInAt(0, Location::Any());
+  LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
+      ? LocationSummary::kCallOnSlowPath
+      : LocationSummary::kNoCall;
+  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+  Location loc = codegen_->IsImplicitNullCheckAllowed(instruction)
+      ? Location::RequiresRegister()
+      : Location::Any();
+  locations->SetInAt(0, loc);
+  if (instruction->HasUses()) {
+    locations->SetOut(Location::SameAsFirstInput());
   }
 }
 
@@ -6403,7 +6409,6 @@
   LocationSummary::CallKind call_kind = LocationSummary::kNoCall;
   bool throws_into_catch = instruction->CanThrowIntoCatchBlock();
   TypeCheckKind type_check_kind = instruction->GetTypeCheckKind();
-  bool baker_read_barrier_slow_path = false;
   switch (type_check_kind) {
     case TypeCheckKind::kExactCheck:
     case TypeCheckKind::kAbstractClassCheck:
@@ -6412,7 +6417,6 @@
       call_kind = (throws_into_catch || kEmitCompilerReadBarrier) ?
           LocationSummary::kCallOnSlowPath :
           LocationSummary::kNoCall;  // In fact, call on a fatal (non-returning) slow path.
-      baker_read_barrier_slow_path = kUseBakerReadBarrier && !throws_into_catch;
       break;
     case TypeCheckKind::kArrayCheck:
     case TypeCheckKind::kUnresolvedCheck:
@@ -6421,9 +6425,6 @@
       break;
   }
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
-  if (baker_read_barrier_slow_path) {
-    locations->SetCustomSlowPathCallerSaves(RegisterSet());  // No caller-save registers.
-  }
   locations->SetInAt(0, Location::RequiresRegister());
   locations->SetInAt(1, Location::Any());
   // Note that TypeCheckSlowPathX86 uses this "temp" register too.
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index e161308..15307fe 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -4459,10 +4459,16 @@
 }
 
 void LocationsBuilderX86_64::VisitNullCheck(HNullCheck* instruction) {
-  LocationSummary* locations = codegen_->CreateNullCheckLocations(instruction);
-  if (!codegen_->GetCompilerOptions().GetImplicitNullChecks()) {
-    // Explicit null checks can use any location.
-    locations->SetInAt(0, Location::Any());
+  LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
+      ? LocationSummary::kCallOnSlowPath
+      : LocationSummary::kNoCall;
+  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+  Location loc = codegen_->IsImplicitNullCheckAllowed(instruction)
+      ? Location::RequiresRegister()
+      : Location::Any();
+  locations->SetInAt(0, loc);
+  if (instruction->HasUses()) {
+    locations->SetOut(Location::SameAsFirstInput());
   }
 }
 
@@ -5825,7 +5831,6 @@
   LocationSummary::CallKind call_kind = LocationSummary::kNoCall;
   bool throws_into_catch = instruction->CanThrowIntoCatchBlock();
   TypeCheckKind type_check_kind = instruction->GetTypeCheckKind();
-  bool baker_read_barrier_slow_path = false;
   switch (type_check_kind) {
     case TypeCheckKind::kExactCheck:
     case TypeCheckKind::kAbstractClassCheck:
@@ -5834,7 +5839,6 @@
       call_kind = (throws_into_catch || kEmitCompilerReadBarrier) ?
           LocationSummary::kCallOnSlowPath :
           LocationSummary::kNoCall;  // In fact, call on a fatal (non-returning) slow path.
-      baker_read_barrier_slow_path = kUseBakerReadBarrier && !throws_into_catch;
       break;
     case TypeCheckKind::kArrayCheck:
     case TypeCheckKind::kUnresolvedCheck:
@@ -5843,9 +5847,6 @@
       break;
   }
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
-  if (baker_read_barrier_slow_path) {
-    locations->SetCustomSlowPathCallerSaves(RegisterSet());  // No caller-save registers.
-  }
   locations->SetInAt(0, Location::RequiresRegister());
   locations->SetInAt(1, Location::Any());
   // Note that TypeCheckSlowPathX86_64 uses this "temp" register too.
diff --git a/compiler/optimizing/codegen_test.cc b/compiler/optimizing/codegen_test.cc
index d00a786..d9347f6 100644
--- a/compiler/optimizing/codegen_test.cc
+++ b/compiler/optimizing/codegen_test.cc
@@ -74,6 +74,24 @@
 
 namespace art {
 
+typedef CodeGenerator* (*CreateCodegenFn)(HGraph*, const CompilerOptions&);
+
+class CodegenTargetConfig {
+ public:
+  CodegenTargetConfig(InstructionSet isa, CreateCodegenFn create_codegen)
+      : isa_(isa), create_codegen_(create_codegen) {
+  }
+  InstructionSet GetInstructionSet() const { return isa_; }
+  CodeGenerator* CreateCodeGenerator(HGraph* graph, const CompilerOptions& compiler_options) {
+    return create_codegen_(graph, compiler_options);
+  }
+
+ private:
+  CodegenTargetConfig() {}
+  InstructionSet isa_;
+  CreateCodegenFn create_codegen_;
+};
+
 #ifdef ART_ENABLE_CODEGEN_arm
 // Provide our own codegen, that ensures the C calling conventions
 // are preserved. Currently, ART and C do not match as R4 is caller-save
@@ -222,12 +240,7 @@
   VerifyGeneratedCode(target_isa, f, has_result, expected);
 }
 
-template <typename Expected>
-static void RunCode(CodeGenerator* codegen,
-                    HGraph* graph,
-                    std::function<void(HGraph*)> hook_before_codegen,
-                    bool has_result,
-                    Expected expected) {
+static void ValidateGraph(HGraph* graph) {
   GraphChecker graph_checker(graph);
   graph_checker.Run();
   if (!graph_checker.IsValid()) {
@@ -236,92 +249,129 @@
     }
   }
   ASSERT_TRUE(graph_checker.IsValid());
+}
 
+template <typename Expected>
+static void RunCodeNoCheck(CodeGenerator* codegen,
+                           HGraph* graph,
+                           std::function<void(HGraph*)> hook_before_codegen,
+                           bool has_result,
+                           Expected expected) {
   SsaLivenessAnalysis liveness(graph, codegen);
-
   PrepareForRegisterAllocation(graph).Run();
   liveness.Analyze();
   RegisterAllocator::Create(graph->GetArena(), codegen, liveness)->AllocateRegisters();
   hook_before_codegen(graph);
-
   InternalCodeAllocator allocator;
   codegen->Compile(&allocator);
   Run(allocator, *codegen, has_result, expected);
 }
 
 template <typename Expected>
-static void RunCode(InstructionSet target_isa,
+static void RunCode(CodeGenerator* codegen,
+                    HGraph* graph,
+                    std::function<void(HGraph*)> hook_before_codegen,
+                    bool has_result,
+                    Expected expected) {
+  ValidateGraph(graph);
+  RunCodeNoCheck(codegen, graph, hook_before_codegen, has_result, expected);
+}
+
+template <typename Expected>
+static void RunCode(CodegenTargetConfig target_config,
                     HGraph* graph,
                     std::function<void(HGraph*)> hook_before_codegen,
                     bool has_result,
                     Expected expected) {
   CompilerOptions compiler_options;
-#ifdef ART_ENABLE_CODEGEN_arm
-  if (target_isa == kArm || target_isa == kThumb2) {
-    std::unique_ptr<const ArmInstructionSetFeatures> features_arm(
-        ArmInstructionSetFeatures::FromCppDefines());
-    TestCodeGeneratorARM codegenARM(graph, *features_arm.get(), compiler_options);
-    RunCode(&codegenARM, graph, hook_before_codegen, has_result, expected);
-  }
-#endif
-#ifdef ART_ENABLE_CODEGEN_arm64
-  if (target_isa == kArm64) {
-    std::unique_ptr<const Arm64InstructionSetFeatures> features_arm64(
-        Arm64InstructionSetFeatures::FromCppDefines());
-    arm64::CodeGeneratorARM64 codegenARM64(graph, *features_arm64.get(), compiler_options);
-    RunCode(&codegenARM64, graph, hook_before_codegen, has_result, expected);
-  }
-#endif
-#ifdef ART_ENABLE_CODEGEN_x86
-  if (target_isa == kX86) {
-    std::unique_ptr<const X86InstructionSetFeatures> features_x86(
-        X86InstructionSetFeatures::FromCppDefines());
-    TestCodeGeneratorX86 codegenX86(graph, *features_x86.get(), compiler_options);
-    RunCode(&codegenX86, graph, hook_before_codegen, has_result, expected);
-  }
-#endif
-#ifdef ART_ENABLE_CODEGEN_x86_64
-  if (target_isa == kX86_64) {
-    std::unique_ptr<const X86_64InstructionSetFeatures> features_x86_64(
-        X86_64InstructionSetFeatures::FromCppDefines());
-    x86_64::CodeGeneratorX86_64 codegenX86_64(graph, *features_x86_64.get(), compiler_options);
-    RunCode(&codegenX86_64, graph, hook_before_codegen, has_result, expected);
-  }
-#endif
-#ifdef ART_ENABLE_CODEGEN_mips
-  if (target_isa == kMips) {
-    std::unique_ptr<const MipsInstructionSetFeatures> features_mips(
-        MipsInstructionSetFeatures::FromCppDefines());
-    mips::CodeGeneratorMIPS codegenMIPS(graph, *features_mips.get(), compiler_options);
-    RunCode(&codegenMIPS, graph, hook_before_codegen, has_result, expected);
-  }
-#endif
-#ifdef ART_ENABLE_CODEGEN_mips64
-  if (target_isa == kMips64) {
-    std::unique_ptr<const Mips64InstructionSetFeatures> features_mips64(
-        Mips64InstructionSetFeatures::FromCppDefines());
-    mips64::CodeGeneratorMIPS64 codegenMIPS64(graph, *features_mips64.get(), compiler_options);
-    RunCode(&codegenMIPS64, graph, hook_before_codegen, has_result, expected);
-  }
-#endif
+  CodeGenerator* codegen = target_config.CreateCodeGenerator(graph, compiler_options);
+  RunCode(codegen, graph, hook_before_codegen, has_result, expected);
 }
 
-static ::std::vector<InstructionSet> GetTargetISAs() {
-  ::std::vector<InstructionSet> v;
-  // Add all ISAs that are executable on hardware or on simulator.
-  const ::std::vector<InstructionSet> executable_isa_candidates = {
-    kArm,
-    kArm64,
-    kThumb2,
-    kX86,
-    kX86_64,
-    kMips,
-    kMips64
+#ifdef ART_ENABLE_CODEGEN_arm
+CodeGenerator* create_codegen_arm(HGraph* graph, const CompilerOptions& compiler_options) {
+  std::unique_ptr<const ArmInstructionSetFeatures> features_arm(
+      ArmInstructionSetFeatures::FromCppDefines());
+  return new (graph->GetArena()) TestCodeGeneratorARM(graph,
+                                                      *features_arm.get(),
+                                                      compiler_options);
+}
+#endif
+
+#ifdef ART_ENABLE_CODEGEN_arm64
+CodeGenerator* create_codegen_arm64(HGraph* graph, const CompilerOptions& compiler_options) {
+  std::unique_ptr<const Arm64InstructionSetFeatures> features_arm64(
+      Arm64InstructionSetFeatures::FromCppDefines());
+  return new (graph->GetArena()) arm64::CodeGeneratorARM64(graph,
+                                                           *features_arm64.get(),
+                                                           compiler_options);
+}
+#endif
+
+#ifdef ART_ENABLE_CODEGEN_x86
+CodeGenerator* create_codegen_x86(HGraph* graph, const CompilerOptions& compiler_options) {
+  std::unique_ptr<const X86InstructionSetFeatures> features_x86(
+      X86InstructionSetFeatures::FromCppDefines());
+  return new (graph->GetArena()) TestCodeGeneratorX86(graph, *features_x86.get(), compiler_options);
+}
+#endif
+
+#ifdef ART_ENABLE_CODEGEN_x86_64
+CodeGenerator* create_codegen_x86_64(HGraph* graph, const CompilerOptions& compiler_options) {
+  std::unique_ptr<const X86_64InstructionSetFeatures> features_x86_64(
+     X86_64InstructionSetFeatures::FromCppDefines());
+  return new (graph->GetArena())
+      x86_64::CodeGeneratorX86_64(graph, *features_x86_64.get(), compiler_options);
+}
+#endif
+
+#ifdef ART_ENABLE_CODEGEN_mips
+CodeGenerator* create_codegen_mips(HGraph* graph, const CompilerOptions& compiler_options) {
+  std::unique_ptr<const MipsInstructionSetFeatures> features_mips(
+      MipsInstructionSetFeatures::FromCppDefines());
+  return new (graph->GetArena())
+      mips::CodeGeneratorMIPS(graph, *features_mips.get(), compiler_options);
+}
+#endif
+
+#ifdef ART_ENABLE_CODEGEN_mips64
+CodeGenerator* create_codegen_mips64(HGraph* graph, const CompilerOptions& compiler_options) {
+  std::unique_ptr<const Mips64InstructionSetFeatures> features_mips64(
+      Mips64InstructionSetFeatures::FromCppDefines());
+  return new (graph->GetArena())
+      mips64::CodeGeneratorMIPS64(graph, *features_mips64.get(), compiler_options);
+}
+#endif
+
+// Return all combinations of ISA and code generator that are executable on
+// hardware, or on simulator, and that we'd like to test.
+static ::std::vector<CodegenTargetConfig> GetTargetConfigs() {
+  ::std::vector<CodegenTargetConfig> v;
+  ::std::vector<CodegenTargetConfig> test_config_candidates = {
+#ifdef ART_ENABLE_CODEGEN_arm
+    CodegenTargetConfig(kArm, create_codegen_arm),
+    CodegenTargetConfig(kThumb2, create_codegen_arm),
+#endif
+#ifdef ART_ENABLE_CODEGEN_arm64
+    CodegenTargetConfig(kArm64, create_codegen_arm64),
+#endif
+#ifdef ART_ENABLE_CODEGEN_x86
+    CodegenTargetConfig(kX86, create_codegen_x86),
+#endif
+#ifdef ART_ENABLE_CODEGEN_x86_64
+    CodegenTargetConfig(kX86_64, create_codegen_x86_64),
+#endif
+#ifdef ART_ENABLE_CODEGEN_mips
+    CodegenTargetConfig(kMips, create_codegen_mips),
+#endif
+#ifdef ART_ENABLE_CODEGEN_mips64
+    CodegenTargetConfig(kMips64, create_codegen_mips64)
+#endif
   };
 
-  for (auto target_isa : executable_isa_candidates) {
-    if (CanExecute(target_isa)) {
-      v.push_back(target_isa);
+  for (auto test_config : test_config_candidates) {
+    if (CanExecute(test_config.GetInstructionSet())) {
+      v.push_back(test_config);
     }
   }
 
@@ -331,26 +381,26 @@
 static void TestCode(const uint16_t* data,
                      bool has_result = false,
                      int32_t expected = 0) {
-  for (InstructionSet target_isa : GetTargetISAs()) {
+  for (CodegenTargetConfig target_config : GetTargetConfigs()) {
     ArenaPool pool;
     ArenaAllocator arena(&pool);
     HGraph* graph = CreateCFG(&arena, data);
     // Remove suspend checks, they cannot be executed in this context.
     RemoveSuspendChecks(graph);
-    RunCode(target_isa, graph, [](HGraph*) {}, has_result, expected);
+    RunCode(target_config, graph, [](HGraph*) {}, has_result, expected);
   }
 }
 
 static void TestCodeLong(const uint16_t* data,
                          bool has_result,
                          int64_t expected) {
-  for (InstructionSet target_isa : GetTargetISAs()) {
+  for (CodegenTargetConfig target_config : GetTargetConfigs()) {
     ArenaPool pool;
     ArenaAllocator arena(&pool);
     HGraph* graph = CreateCFG(&arena, data, Primitive::kPrimLong);
     // Remove suspend checks, they cannot be executed in this context.
     RemoveSuspendChecks(graph);
-    RunCode(target_isa, graph, [](HGraph*) {}, has_result, expected);
+    RunCode(target_config, graph, [](HGraph*) {}, has_result, expected);
   }
 }
 
@@ -667,7 +717,7 @@
 }
 
 TEST_F(CodegenTest, NonMaterializedCondition) {
-  for (InstructionSet target_isa : GetTargetISAs()) {
+  for (CodegenTargetConfig target_config : GetTargetConfigs()) {
     ArenaPool pool;
     ArenaAllocator allocator(&pool);
 
@@ -715,12 +765,12 @@
       block->InsertInstructionBefore(move, block->GetLastInstruction());
     };
 
-    RunCode(target_isa, graph, hook_before_codegen, true, 0);
+    RunCode(target_config, graph, hook_before_codegen, true, 0);
   }
 }
 
 TEST_F(CodegenTest, MaterializedCondition1) {
-  for (InstructionSet target_isa : GetTargetISAs()) {
+  for (CodegenTargetConfig target_config : GetTargetConfigs()) {
     // Check that condition are materialized correctly. A materialized condition
     // should yield `1` if it evaluated to true, and `0` otherwise.
     // We force the materialization of comparisons for different combinations of
@@ -762,13 +812,13 @@
         HParallelMove* move = new (graph_in->GetArena()) HParallelMove(graph_in->GetArena());
         block->InsertInstructionBefore(move, block->GetLastInstruction());
       };
-      RunCode(target_isa, graph, hook_before_codegen, true, lhs[i] < rhs[i]);
+      RunCode(target_config, graph, hook_before_codegen, true, lhs[i] < rhs[i]);
     }
   }
 }
 
 TEST_F(CodegenTest, MaterializedCondition2) {
-  for (InstructionSet target_isa : GetTargetISAs()) {
+  for (CodegenTargetConfig target_config : GetTargetConfigs()) {
     // Check that HIf correctly interprets a materialized condition.
     // We force the materialization of comparisons for different combinations of
     // inputs. An HIf takes the materialized combination as input and returns a
@@ -830,7 +880,7 @@
         HParallelMove* move = new (graph_in->GetArena()) HParallelMove(graph_in->GetArena());
         block->InsertInstructionBefore(move, block->GetLastInstruction());
       };
-      RunCode(target_isa, graph, hook_before_codegen, true, lhs[i] < rhs[i]);
+      RunCode(target_config, graph, hook_before_codegen, true, lhs[i] < rhs[i]);
     }
   }
 }
@@ -859,7 +909,7 @@
                            int64_t i,
                            int64_t j,
                            Primitive::Type type,
-                           const InstructionSet target_isa) {
+                           const CodegenTargetConfig target_config) {
   ArenaPool pool;
   ArenaAllocator allocator(&pool);
   HGraph* graph = CreateGraph(&allocator);
@@ -941,23 +991,16 @@
   block->AddInstruction(new (&allocator) HReturn(comparison));
 
   graph->BuildDominatorTree();
-  RunCode(target_isa, graph, [](HGraph*) {}, true, expected_result);
+  RunCode(target_config, graph, [](HGraph*) {}, true, expected_result);
 }
 
 TEST_F(CodegenTest, ComparisonsInt) {
-  for (InstructionSet target_isa : GetTargetISAs()) {
+  for (CodegenTargetConfig target_config : GetTargetConfigs()) {
     for (int64_t i = -1; i <= 1; i++) {
       for (int64_t j = -1; j <= 1; j++) {
-        TestComparison(kCondEQ, i, j, Primitive::kPrimInt, target_isa);
-        TestComparison(kCondNE, i, j, Primitive::kPrimInt, target_isa);
-        TestComparison(kCondLT, i, j, Primitive::kPrimInt, target_isa);
-        TestComparison(kCondLE, i, j, Primitive::kPrimInt, target_isa);
-        TestComparison(kCondGT, i, j, Primitive::kPrimInt, target_isa);
-        TestComparison(kCondGE, i, j, Primitive::kPrimInt, target_isa);
-        TestComparison(kCondB,  i, j, Primitive::kPrimInt, target_isa);
-        TestComparison(kCondBE, i, j, Primitive::kPrimInt, target_isa);
-        TestComparison(kCondA,  i, j, Primitive::kPrimInt, target_isa);
-        TestComparison(kCondAE, i, j, Primitive::kPrimInt, target_isa);
+        for (int cond = kCondFirst; cond <= kCondLast; cond++) {
+          TestComparison(static_cast<IfCondition>(cond), i, j, Primitive::kPrimInt, target_config);
+        }
       }
     }
   }
@@ -969,23 +1012,17 @@
     return;
   }
 
-  for (InstructionSet target_isa : GetTargetISAs()) {
-    if (target_isa == kMips || target_isa == kMips64) {
+  for (CodegenTargetConfig target_config : GetTargetConfigs()) {
+    if ((target_config.GetInstructionSet() == kMips) ||
+        (target_config.GetInstructionSet() == kMips64)) {
       continue;
     }
 
     for (int64_t i = -1; i <= 1; i++) {
       for (int64_t j = -1; j <= 1; j++) {
-        TestComparison(kCondEQ, i, j, Primitive::kPrimLong, target_isa);
-        TestComparison(kCondNE, i, j, Primitive::kPrimLong, target_isa);
-        TestComparison(kCondLT, i, j, Primitive::kPrimLong, target_isa);
-        TestComparison(kCondLE, i, j, Primitive::kPrimLong, target_isa);
-        TestComparison(kCondGT, i, j, Primitive::kPrimLong, target_isa);
-        TestComparison(kCondGE, i, j, Primitive::kPrimLong, target_isa);
-        TestComparison(kCondB,  i, j, Primitive::kPrimLong, target_isa);
-        TestComparison(kCondBE, i, j, Primitive::kPrimLong, target_isa);
-        TestComparison(kCondA,  i, j, Primitive::kPrimLong, target_isa);
-        TestComparison(kCondAE, i, j, Primitive::kPrimLong, target_isa);
+        for (int cond = kCondFirst; cond <= kCondLast; cond++) {
+          TestComparison(static_cast<IfCondition>(cond), i, j, Primitive::kPrimLong, target_config);
+        }
       }
     }
   }
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 149a71d..99d7673 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -109,6 +109,9 @@
   kCondBE,  // <=
   kCondA,   // >
   kCondAE,  // >=
+  // First and last aliases.
+  kCondFirst = kCondEQ,
+  kCondLast = kCondAE,
 };
 
 enum GraphAnalysisResult {
diff --git a/disassembler/Android.bp b/disassembler/Android.bp
index d06e4de..b074d9f 100644
--- a/disassembler/Android.bp
+++ b/disassembler/Android.bp
@@ -26,9 +26,9 @@
         "disassembler_mips.cc",
         "disassembler_x86.cc",
     ],
+    include_dirs: ["art/runtime"],
 
     shared_libs: [
-        "liblog",
         "libbase",
     ],
     export_include_dirs: ["."],
@@ -38,9 +38,8 @@
     name: "libart-disassembler",
     defaults: ["libart-disassembler-defaults"],
     shared_libs: [
-        "libart",
         // For disassembler_arm64.
-        "libvixld-arm64",
+        "libvixl-arm64",
     ],
 }
 
@@ -51,7 +50,6 @@
         "art_debug_defaults",
     ],
     shared_libs: [
-        "libartd",
         // For disassembler_arm64.
         "libvixld-arm64",
     ],
diff --git a/runtime/Android.bp b/runtime/Android.bp
index a884505..b61976c 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -155,6 +155,7 @@
         "native/java_lang_reflect_Constructor.cc",
         "native/java_lang_reflect_Field.cc",
         "native/java_lang_reflect_Method.cc",
+        "native/java_lang_reflect_Parameter.cc",
         "native/java_lang_reflect_Proxy.cc",
         "native/java_util_concurrent_atomic_AtomicLong.cc",
         "native/libcore_util_CharsetUtils.cc",
diff --git a/runtime/arch/arm/fault_handler_arm.cc b/runtime/arch/arm/fault_handler_arm.cc
index daa2dff..befdd48 100644
--- a/runtime/arch/arm/fault_handler_arm.cc
+++ b/runtime/arch/arm/fault_handler_arm.cc
@@ -122,16 +122,13 @@
   struct ucontext *uc = reinterpret_cast<struct ucontext*>(context);
   struct sigcontext *sc = reinterpret_cast<struct sigcontext*>(&uc->uc_mcontext);
   uint8_t* ptr = reinterpret_cast<uint8_t*>(sc->arm_pc);
-  uint32_t instr_size = GetInstructionSize(ptr);
-  uintptr_t gc_map_location = (sc->arm_pc + instr_size) | 1;
 
-  // Push the gc map location to the stack and pass the fault address in LR.
-  sc->arm_sp -= sizeof(uintptr_t);
-  *reinterpret_cast<uintptr_t*>(sc->arm_sp) = gc_map_location;
-  sc->arm_lr = reinterpret_cast<uintptr_t>(info->si_addr);
+  uint32_t instr_size = GetInstructionSize(ptr);
+  sc->arm_lr = (sc->arm_pc + instr_size) | 1;      // LR needs to point to gc map location
   sc->arm_pc = reinterpret_cast<uintptr_t>(art_quick_throw_null_pointer_exception_from_signal);
   // Pass the faulting address as the first argument of
   // art_quick_throw_null_pointer_exception_from_signal.
+  sc->arm_r0 = reinterpret_cast<uintptr_t>(info->si_addr);
   VLOG(signals) << "Generating null pointer exception";
   return true;
 }
diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S
index 3fc83ba..a3f053b 100644
--- a/runtime/arch/arm/quick_entrypoints_arm.S
+++ b/runtime/arch/arm/quick_entrypoints_arm.S
@@ -173,29 +173,6 @@
     /*
      * Macro that sets up the callee save frame to conform with
      * Runtime::CreateCalleeSaveMethod(kSaveEverything)
-     * when core registers are already saved.
-     */
-.macro SETUP_SAVE_EVERYTHING_FRAME_CORE_REGS_SAVED rTemp
-                                        @ 14 words of callee saves and args already saved.
-    vpush {d0-d15}                      @ 32 words, 2 for each of the 16 saved doubles.
-    .cfi_adjust_cfa_offset 128
-    sub sp, #8                          @ 2 words of space, alignment padding and Method*
-    .cfi_adjust_cfa_offset 8
-    RUNTIME_CURRENT1 \rTemp             @ Load Runtime::Current into rTemp.
-    @ Load kSaveEverything Method* into rTemp.
-    ldr \rTemp, [\rTemp, #RUNTIME_SAVE_EVERYTHING_METHOD_OFFSET]
-    str \rTemp, [sp, #0]                @ Place Method* at bottom of stack.
-    str sp, [r9, #THREAD_TOP_QUICK_FRAME_OFFSET]  @ Place sp in Thread::Current()->top_quick_frame.
-
-    // Ugly compile-time check, but we only have the preprocessor.
-#if (FRAME_SIZE_SAVE_EVERYTHING != 56 + 128 + 8)
-#error "FRAME_SIZE_SAVE_EVERYTHING(ARM) size not as expected."
-#endif
-.endm
-
-    /*
-     * Macro that sets up the callee save frame to conform with
-     * Runtime::CreateCalleeSaveMethod(kSaveEverything)
      */
 .macro SETUP_SAVE_EVERYTHING_FRAME rTemp
     push {r0-r12, lr}                   @ 14 words of callee saves and args.
@@ -214,7 +191,20 @@
     .cfi_rel_offset r11, 44
     .cfi_rel_offset ip, 48
     .cfi_rel_offset lr, 52
-    SETUP_SAVE_EVERYTHING_FRAME_CORE_REGS_SAVED \rTemp
+    vpush {d0-d15}                      @ 32 words, 2 for each of the 16 saved doubles.
+    .cfi_adjust_cfa_offset 128
+    sub sp, #8                          @ 2 words of space, alignment padding and Method*
+    .cfi_adjust_cfa_offset 8
+    RUNTIME_CURRENT1 \rTemp             @ Load Runtime::Current into rTemp.
+    @ Load kSaveEverything Method* into rTemp.
+    ldr \rTemp, [\rTemp, #RUNTIME_SAVE_EVERYTHING_METHOD_OFFSET]
+    str \rTemp, [sp, #0]                @ Place Method* at bottom of stack.
+    str sp, [r9, #THREAD_TOP_QUICK_FRAME_OFFSET]  @ Place sp in Thread::Current()->top_quick_frame.
+
+    // Ugly compile-time check, but we only have the preprocessor.
+#if (FRAME_SIZE_SAVE_EVERYTHING != 56 + 128 + 8)
+#error "FRAME_SIZE_SAVE_EVERYTHING(ARM) size not as expected."
+#endif
 .endm
 
 .macro RESTORE_SAVE_EVERYTHING_FRAME
@@ -366,34 +356,7 @@
     /*
      * Call installed by a signal handler to create and deliver a NullPointerException.
      */
-    .extern art_quick_throw_null_pointer_exception_from_signal
-ENTRY art_quick_throw_null_pointer_exception_from_signal
-    // The fault handler pushes the gc map address, i.e. "return address", to stack
-    // and passes the fault address in LR. So we need to set up the CFI info accordingly.
-    .cfi_def_cfa_offset __SIZEOF_POINTER__
-    .cfi_rel_offset lr, 0
-    push {r0-r12}                   @ 13 words of callee saves and args; LR already saved.
-    .cfi_adjust_cfa_offset 52
-    .cfi_rel_offset r0, 0
-    .cfi_rel_offset r1, 4
-    .cfi_rel_offset r2, 8
-    .cfi_rel_offset r3, 12
-    .cfi_rel_offset r4, 16
-    .cfi_rel_offset r5, 20
-    .cfi_rel_offset r6, 24
-    .cfi_rel_offset r7, 28
-    .cfi_rel_offset r8, 32
-    .cfi_rel_offset r9, 36
-    .cfi_rel_offset r10, 40
-    .cfi_rel_offset r11, 44
-    .cfi_rel_offset ip, 48
-
-    @ save all registers as basis for long jump context
-    SETUP_SAVE_EVERYTHING_FRAME_CORE_REGS_SAVED r1
-    mov r0, lr                      @ pass the fault address stored in LR by the fault handler.
-    mov r1, r9                      @ pass Thread::Current
-    b   artThrowNullPointerExceptionFromSignal  @ (Thread*)
-END art_quick_throw_null_pointer_exception_from_signal
+ONE_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception_from_signal, artThrowNullPointerExceptionFromSignal
 
     /*
      * Called by managed code to create and deliver an ArithmeticException.
diff --git a/runtime/arch/arm64/fault_handler_arm64.cc b/runtime/arch/arm64/fault_handler_arm64.cc
index c02be87..6724d6d 100644
--- a/runtime/arch/arm64/fault_handler_arm64.cc
+++ b/runtime/arch/arm64/fault_handler_arm64.cc
@@ -96,12 +96,12 @@
   struct ucontext *uc = reinterpret_cast<struct ucontext*>(context);
   struct sigcontext *sc = reinterpret_cast<struct sigcontext*>(&uc->uc_mcontext);
 
-  // Push the gc map location to the stack and pass the fault address in LR.
-  sc->sp -= sizeof(uintptr_t);
-  *reinterpret_cast<uintptr_t*>(sc->sp) = sc->pc + 4;
-  sc->regs[30] = reinterpret_cast<uintptr_t>(info->si_addr);
+  sc->regs[30] = sc->pc + 4;      // LR needs to point to gc map location
 
   sc->pc = reinterpret_cast<uintptr_t>(art_quick_throw_null_pointer_exception_from_signal);
+  // Pass the faulting address as the first argument of
+  // art_quick_throw_null_pointer_exception_from_signal.
+  sc->regs[0] = reinterpret_cast<uintptr_t>(info->si_addr);
   VLOG(signals) << "Generating null pointer exception";
   return true;
 }
diff --git a/runtime/arch/arm64/quick_entrypoints_arm64.S b/runtime/arch/arm64/quick_entrypoints_arm64.S
index ea4669d..25aa8ce 100644
--- a/runtime/arch/arm64/quick_entrypoints_arm64.S
+++ b/runtime/arch/arm64/quick_entrypoints_arm64.S
@@ -265,10 +265,10 @@
     /*
      * Macro that sets up the callee save frame to conform with
      * Runtime::CreateCalleeSaveMethod(kSaveEverything)
-     * when the SP has already been decremented by FRAME_SIZE_SAVE_EVERYTHING
-     * and saving registers x29 and LR is handled elsewhere.
      */
-.macro SETUP_SAVE_EVERYTHING_FRAME_DECREMENTED_SP_SKIP_X29_LR
+.macro SETUP_SAVE_EVERYTHING_FRAME
+    INCREASE_FRAME 512
+
     // Ugly compile-time check, but we only have the preprocessor.
 #if (FRAME_SIZE_SAVE_EVERYTHING != 512)
 #error "FRAME_SIZE_SAVE_EVERYTHING(ARM64) size not as expected."
@@ -310,6 +310,7 @@
     SAVE_TWO_REGS x23, x24, 448
     SAVE_TWO_REGS x25, x26, 464
     SAVE_TWO_REGS x27, x28, 480
+    SAVE_TWO_REGS x29, xLR, 496
 
     // art::Runtime** xIP0 = &art::Runtime::instance_
     adrp xIP0, :got:_ZN3art7Runtime9instance_E
@@ -327,16 +328,6 @@
     str xIP0, [xSELF, # THREAD_TOP_QUICK_FRAME_OFFSET]
 .endm
 
-    /*
-     * Macro that sets up the callee save frame to conform with
-     * Runtime::CreateCalleeSaveMethod(kSaveEverything)
-     */
-.macro SETUP_SAVE_EVERYTHING_FRAME
-    INCREASE_FRAME 512
-    SAVE_TWO_REGS x29, xLR, 496
-    SETUP_SAVE_EVERYTHING_FRAME_DECREMENTED_SP_SKIP_X29_LR
-.endm
-
 .macro RESTORE_SAVE_EVERYTHING_FRAME
     // Restore FP registers.
     // For better performance, load d0 and d31 separately, so that all LDPs are 16-byte aligned.
@@ -471,21 +462,7 @@
     /*
      * Call installed by a signal handler to create and deliver a NullPointerException.
      */
-    .extern art_quick_throw_null_pointer_exception_from_signal
-ENTRY art_quick_throw_null_pointer_exception_from_signal
-    // The fault handler pushes the gc map address, i.e. "return address", to stack
-    // and passes the fault address in LR. So we need to set up the CFI info accordingly.
-    .cfi_def_cfa_offset __SIZEOF_POINTER__
-    .cfi_rel_offset lr, 0
-    // Save all registers as basis for long jump context.
-    INCREASE_FRAME (FRAME_SIZE_SAVE_EVERYTHING - __SIZEOF_POINTER__)
-    SAVE_REG x29, (FRAME_SIZE_SAVE_EVERYTHING - 2 * __SIZEOF_POINTER__)  // LR already saved.
-    SETUP_SAVE_EVERYTHING_FRAME_DECREMENTED_SP_SKIP_X29_LR
-    mov x0, lr                        // pass the fault address stored in LR by the fault handler.
-    mov x1, xSELF                     // pass Thread::Current.
-    b   artThrowNullPointerExceptionFromSignal  // (arg, Thread*).
-    brk 0
-END art_quick_throw_null_pointer_exception_from_signal
+ONE_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception_from_signal, artThrowNullPointerExceptionFromSignal
 
     /*
      * Called by managed code to create and deliver an ArithmeticException.
diff --git a/runtime/arch/mips/asm_support_mips.S b/runtime/arch/mips/asm_support_mips.S
index 7955b1d..801f708 100644
--- a/runtime/arch/mips/asm_support_mips.S
+++ b/runtime/arch/mips/asm_support_mips.S
@@ -43,7 +43,7 @@
 .endm
 
      // Declare a function called name, doesn't set up $gp.
-.macro ENTRY_NO_GP_CUSTOM_CFA name, cfa_offset
+.macro ENTRY_NO_GP name
     .type \name, %function
     .global \name
     // Cache alignment for function entry.
@@ -51,12 +51,7 @@
 \name:
     .cfi_startproc
      // Ensure we get a sane starting CFA.
-    .cfi_def_cfa $sp, \cfa_offset
-.endm
-
-     // Declare a function called name, doesn't set up $gp.
-.macro ENTRY_NO_GP name
-    ENTRY_NO_GP_CUSTOM_CFA \name, 0
+    .cfi_def_cfa $sp,0
 .endm
 
 .macro END name
diff --git a/runtime/arch/mips/fault_handler_mips.cc b/runtime/arch/mips/fault_handler_mips.cc
index b6a63ca..7969a8f 100644
--- a/runtime/arch/mips/fault_handler_mips.cc
+++ b/runtime/arch/mips/fault_handler_mips.cc
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "arch/mips/quick_method_frame_info_mips.h"
+
 #include "fault_handler.h"
 #include <sys/ucontext.h>
 #include "art_method-inl.h"
@@ -82,15 +82,12 @@
   struct ucontext *uc = reinterpret_cast<struct ucontext*>(context);
   struct sigcontext *sc = reinterpret_cast<struct sigcontext*>(&uc->uc_mcontext);
 
-  // Decrement $sp by the frame size of the kSaveEverything method and store
-  // the fault address in the padding right after the ArtMethod*.
-  sc->sc_regs[mips::SP] -= mips::MipsCalleeSaveFrameSize(Runtime::kSaveEverything);
-  uintptr_t* padding = reinterpret_cast<uintptr_t*>(sc->sc_regs[mips::SP]) + /* ArtMethod* */ 1;
-  *padding = reinterpret_cast<uintptr_t>(info->si_addr);
-
   sc->sc_regs[mips::RA] = sc->sc_pc + 4;      // RA needs to point to gc map location
   sc->sc_pc = reinterpret_cast<uintptr_t>(art_quick_throw_null_pointer_exception_from_signal);
   sc->sc_regs[mips::T9] = sc->sc_pc;          // make sure T9 points to the function
+  // Pass the faulting address as the first argument of
+  // art_quick_throw_null_pointer_exception_from_signal.
+  sc->sc_regs[mips::A0] = reinterpret_cast<uintptr_t>(info->si_addr);
   VLOG(signals) << "Generating null pointer exception";
   return true;
 }
diff --git a/runtime/arch/mips/quick_entrypoints_mips.S b/runtime/arch/mips/quick_entrypoints_mips.S
index 71b8ae2..4bd1314 100644
--- a/runtime/arch/mips/quick_entrypoints_mips.S
+++ b/runtime/arch/mips/quick_entrypoints_mips.S
@@ -279,7 +279,6 @@
     /*
      * Macro that sets up the callee save frame to conform with
      * Runtime::CreateCalleeSaveMethod(kSaveEverything).
-     * when the $sp has already been decremented by FRAME_SIZE_SAVE_EVERYTHING.
      * Callee-save: $at, $v0-$v1, $a0-$a3, $t0-$t7, $s0-$s7, $t8-$t9, $gp, $fp $ra, $f0-$f31;
      *              28(GPR)+ 32(FPR) + 3 words for padding and 1 word for Method*
      * Clobbers $t0 and $t1.
@@ -287,7 +286,10 @@
      * Reserves FRAME_SIZE_SAVE_EVERYTHING + ARG_SLOT_SIZE bytes on the stack.
      * This macro sets up $gp; entrypoints using it should start with ENTRY_NO_GP.
      */
-.macro SETUP_SAVE_EVERYTHING_FRAME_DECREMENTED_SP
+.macro SETUP_SAVE_EVERYTHING_FRAME
+    addiu  $sp, $sp, -256
+    .cfi_adjust_cfa_offset 256
+
      // Ugly compile-time check, but we only have the preprocessor.
 #if (FRAME_SIZE_SAVE_EVERYTHING != 256)
 #error "FRAME_SIZE_SAVE_EVERYTHING(MIPS) size not as expected."
@@ -386,22 +388,6 @@
     .cfi_adjust_cfa_offset ARG_SLOT_SIZE
 .endm
 
-    /*
-     * Macro that sets up the callee save frame to conform with
-     * Runtime::CreateCalleeSaveMethod(kSaveEverything).
-     * Callee-save: $at, $v0-$v1, $a0-$a3, $t0-$t7, $s0-$s7, $t8-$t9, $gp, $fp $ra, $f0-$f31;
-     *              28(GPR)+ 32(FPR) + 3 words for padding and 1 word for Method*
-     * Clobbers $t0 and $t1.
-     * Allocates ARG_SLOT_SIZE bytes at the bottom of the stack for arg slots.
-     * Reserves FRAME_SIZE_SAVE_EVERYTHING + ARG_SLOT_SIZE bytes on the stack.
-     * This macro sets up $gp; entrypoints using it should start with ENTRY_NO_GP.
-     */
-.macro SETUP_SAVE_EVERYTHING_FRAME
-    addiu  $sp, $sp, -(FRAME_SIZE_SAVE_EVERYTHING)
-    .cfi_adjust_cfa_offset (FRAME_SIZE_SAVE_EVERYTHING)
-    SETUP_SAVE_EVERYTHING_FRAME_DECREMENTED_SP
-.endm
-
 .macro RESTORE_SAVE_EVERYTHING_FRAME
     addiu  $sp, $sp, ARG_SLOT_SIZE                # remove argument slots on the stack
     .cfi_adjust_cfa_offset -ARG_SLOT_SIZE
@@ -722,10 +708,8 @@
      * Call installed by a signal handler to create and deliver a NullPointerException.
      */
     .extern artThrowNullPointerExceptionFromSignal
-ENTRY_NO_GP_CUSTOM_CFA art_quick_throw_null_pointer_exception_from_signal, FRAME_SIZE_SAVE_EVERYTHING
-    SETUP_SAVE_EVERYTHING_FRAME_DECREMENTED_SP
-    # Retrieve the fault address from the padding where the signal handler stores it.
-    lw   $a0, (ARG_SLOT_SIZE + __SIZEOF_POINTER__)($sp)
+ENTRY art_quick_throw_null_pointer_exception_from_signal
+    SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
     la   $t9, artThrowNullPointerExceptionFromSignal
     jalr $zero, $t9                 # artThrowNullPointerExceptionFromSignal(uintptr_t, Thread*)
     move $a1, rSELF                 # pass Thread::Current
diff --git a/runtime/arch/mips64/asm_support_mips64.S b/runtime/arch/mips64/asm_support_mips64.S
index 6c58fcf..786e860 100644
--- a/runtime/arch/mips64/asm_support_mips64.S
+++ b/runtime/arch/mips64/asm_support_mips64.S
@@ -45,8 +45,8 @@
 .L\name\()_gp_set:
 .endm
 
-    // Declare a function called name, doesn't set up $gp.
-.macro ENTRY_NO_GP_CUSTOM_CFA name, cfa_offset
+     // Declare a function called name, doesn't set up $gp.
+.macro ENTRY_NO_GP name
     .type \name, %function
     .global \name
     // Cache alignment for function entry.
@@ -54,12 +54,7 @@
 \name:
     .cfi_startproc
      // Ensure we get a sane starting CFA.
-    .cfi_def_cfa $sp, \cfa_offset
-.endm
-
-    // Declare a function called name, doesn't set up $gp.
-.macro ENTRY_NO_GP name
-    ENTRY_NO_GP_CUSTOM_CFA \name, 0
+    .cfi_def_cfa $sp,0
 .endm
 
 .macro END name
diff --git a/runtime/arch/mips64/fault_handler_mips64.cc b/runtime/arch/mips64/fault_handler_mips64.cc
index e52dc73..0bbb6e1 100644
--- a/runtime/arch/mips64/fault_handler_mips64.cc
+++ b/runtime/arch/mips64/fault_handler_mips64.cc
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "arch/mips64/quick_method_frame_info_mips64.h"
+
 #include "fault_handler.h"
 #include <sys/ucontext.h>
 #include "art_method-inl.h"
@@ -83,15 +83,12 @@
   struct ucontext *uc = reinterpret_cast<struct ucontext*>(context);
   struct sigcontext *sc = reinterpret_cast<struct sigcontext*>(&uc->uc_mcontext);
 
-  // Decrement $sp by the frame size of the kSaveEverything method and store
-  // the fault address in the padding right after the ArtMethod*.
-  sc->sc_regs[mips64::SP] -= mips64::Mips64CalleeSaveFrameSize(Runtime::kSaveEverything);
-  uintptr_t* padding = reinterpret_cast<uintptr_t*>(sc->sc_regs[mips64::SP]) + /* ArtMethod* */ 1;
-  *padding = reinterpret_cast<uintptr_t>(info->si_addr);
-
   sc->sc_regs[mips64::RA] = sc->sc_pc + 4;      // RA needs to point to gc map location
   sc->sc_pc = reinterpret_cast<uintptr_t>(art_quick_throw_null_pointer_exception_from_signal);
   sc->sc_regs[mips64::T9] = sc->sc_pc;          // make sure T9 points to the function
+  // Pass the faulting address as the first argument of
+  // art_quick_throw_null_pointer_exception_from_signal.
+  sc->sc_regs[mips64::A0] = reinterpret_cast<uintptr_t>(info->si_addr);
   VLOG(signals) << "Generating null pointer exception";
   return true;
 }
diff --git a/runtime/arch/mips64/quick_entrypoints_mips64.S b/runtime/arch/mips64/quick_entrypoints_mips64.S
index 61c9019..26717ad 100644
--- a/runtime/arch/mips64/quick_entrypoints_mips64.S
+++ b/runtime/arch/mips64/quick_entrypoints_mips64.S
@@ -316,12 +316,14 @@
     /*
      * Macro that sets up the callee save frame to conform with
      * Runtime::CreateCalleeSaveMethod(kSaveEverything).
-     * when the $sp has already been decremented by FRAME_SIZE_SAVE_EVERYTHING.
      * callee-save: $at + $v0-$v1 + $a0-$a7 + $t0-$t3 + $s0-$s7 + $t8-$t9 + $gp + $s8 + $ra + $s8,
      *              $f0-$f31; 28(GPR)+ 32(FPR) + 1x8 bytes padding + method*
      * This macro sets up $gp; entrypoints using it should start with ENTRY_NO_GP.
      */
-.macro SETUP_SAVE_EVERYTHING_FRAME_DECREMENTED_SP
+.macro SETUP_SAVE_EVERYTHING_FRAME
+    daddiu $sp, $sp, -496
+    .cfi_adjust_cfa_offset 496
+
      // Ugly compile-time check, but we only have the preprocessor.
 #if (FRAME_SIZE_SAVE_EVERYTHING != 496)
 #error "FRAME_SIZE_SAVE_EVERYTHING(MIPS64) size not as expected."
@@ -434,19 +436,6 @@
     sd      $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF)
 .endm
 
-    /*
-     * Macro that sets up the callee save frame to conform with
-     * Runtime::CreateCalleeSaveMethod(kSaveEverything).
-     * callee-save: $at + $v0-$v1 + $a0-$a7 + $t0-$t3 + $s0-$s7 + $t8-$t9 + $gp + $s8 + $ra + $s8,
-     *              $f0-$f31; 28(GPR)+ 32(FPR) + 1x8 bytes padding + method*
-     * This macro sets up $gp; entrypoints using it should start with ENTRY_NO_GP.
-     */
-.macro SETUP_SAVE_EVERYTHING_FRAME
-    daddiu $sp, $sp, -(FRAME_SIZE_SAVE_EVERYTHING)
-    .cfi_adjust_cfa_offset (FRAME_SIZE_SAVE_EVERYTHING)
-    SETUP_SAVE_EVERYTHING_FRAME_DECREMENTED_SP
-.endm
-
 .macro RESTORE_SAVE_EVERYTHING_FRAME
     // Restore FP registers.
     l.d    $f31, 264($sp)
@@ -829,10 +818,8 @@
      * Call installed by a signal handler to create and deliver a NullPointerException
      */
     .extern artThrowNullPointerExceptionFromSignal
-ENTRY_NO_GP_CUSTOM_CFA art_quick_throw_null_pointer_exception_from_signal, FRAME_SIZE_SAVE_EVERYTHING
-    SETUP_SAVE_EVERYTHING_FRAME_DECREMENTED_SP
-    # Retrieve the fault address from the padding where the signal handler stores it.
-    ld   $a0, (__SIZEOF_POINTER__)($sp)
+ENTRY art_quick_throw_null_pointer_exception_from_signal
+    SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
     dla  $t9, artThrowNullPointerExceptionFromSignal
     jalr $zero, $t9                 # artThrowNullPointerExceptionFromSignal(uinptr_t, Thread*)
     move $a1, rSELF                 # pass Thread::Current
diff --git a/runtime/arch/x86/asm_support_x86.S b/runtime/arch/x86/asm_support_x86.S
index 14b01c5..3e47209 100644
--- a/runtime/arch/x86/asm_support_x86.S
+++ b/runtime/arch/x86/asm_support_x86.S
@@ -114,7 +114,7 @@
     .balign 16
 END_MACRO
 
-MACRO2(DEFINE_FUNCTION_CUSTOM_CFA, c_name, cfa_offset)
+MACRO1(DEFINE_FUNCTION, c_name)
     FUNCTION_TYPE(SYMBOL(\c_name))
     ASM_HIDDEN CALLVAR(c_name)
     .globl CALLVAR(c_name)
@@ -122,11 +122,7 @@
 CALLVAR(c_name):
     CFI_STARTPROC
     // Ensure we get a sane starting CFA.
-    CFI_DEF_CFA(esp, RAW_VAR(cfa_offset))
-END_MACRO
-
-MACRO1(DEFINE_FUNCTION, c_name)
-    DEFINE_FUNCTION_CUSTOM_CFA RAW_VAR(c_name), __SIZEOF_POINTER__
+    CFI_DEF_CFA(esp, 4)
 END_MACRO
 
 MACRO1(END_FUNCTION, c_name)
diff --git a/runtime/arch/x86/fault_handler_x86.cc b/runtime/arch/x86/fault_handler_x86.cc
index a4d6bb4..c7af249 100644
--- a/runtime/arch/x86/fault_handler_x86.cc
+++ b/runtime/arch/x86/fault_handler_x86.cc
@@ -325,15 +325,21 @@
   // next instruction (this instruction + instruction size).  The return address
   // is on the stack at the top address of the current frame.
 
-  // Push the return address and fault address onto the stack.
+  // Push the return address onto the stack.
   uintptr_t retaddr = reinterpret_cast<uintptr_t>(pc + instr_size);
-  uintptr_t* next_sp = reinterpret_cast<uintptr_t*>(sp - 2 * sizeof(uintptr_t));
-  next_sp[1] = retaddr;
-  next_sp[0] = reinterpret_cast<uintptr_t>(sig->si_addr);
+  uintptr_t* next_sp = reinterpret_cast<uintptr_t*>(sp - sizeof(uintptr_t));
+  *next_sp = retaddr;
   uc->CTX_ESP = reinterpret_cast<uintptr_t>(next_sp);
 
   uc->CTX_EIP = reinterpret_cast<uintptr_t>(
       art_quick_throw_null_pointer_exception_from_signal);
+  // Pass the faulting address as the first argument of
+  // art_quick_throw_null_pointer_exception_from_signal.
+#if defined(__x86_64__)
+  uc->CTX_RDI = reinterpret_cast<uintptr_t>(sig->si_addr);
+#else
+  uc->CTX_EAX = reinterpret_cast<uintptr_t>(sig->si_addr);
+#endif
   VLOG(signals) << "Generating null pointer exception";
   return true;
 }
diff --git a/runtime/arch/x86/quick_entrypoints_x86.S b/runtime/arch/x86/quick_entrypoints_x86.S
index 0beb2a4..646a80c 100644
--- a/runtime/arch/x86/quick_entrypoints_x86.S
+++ b/runtime/arch/x86/quick_entrypoints_x86.S
@@ -224,11 +224,10 @@
     /*
      * Macro that sets up the callee save frame to conform with
      * Runtime::CreateCalleeSaveMethod(kSaveEverything)
-     * when EDI is already saved.
      */
-MACRO2(SETUP_SAVE_EVERYTHING_FRAME_EDI_SAVED, got_reg, temp_reg)
-    // Save core registers from highest to lowest to agree with core spills bitmap.
-    // EDI, or at least a placeholder for it, is already on the stack.
+MACRO2(SETUP_SAVE_EVERYTHING_FRAME, got_reg, temp_reg)
+    // Save core registers.
+    PUSH edi
     PUSH esi
     PUSH ebp
     PUSH ebx
@@ -265,15 +264,6 @@
 #endif
 END_MACRO
 
-    /*
-     * Macro that sets up the callee save frame to conform with
-     * Runtime::CreateCalleeSaveMethod(kSaveEverything)
-     */
-MACRO2(SETUP_SAVE_EVERYTHING_FRAME, got_reg, temp_reg)
-    PUSH edi
-    SETUP_SAVE_EVERYTHING_FRAME_EDI_SAVED RAW_VAR(got_reg), RAW_VAR(temp_reg)
-END_MACRO
-
 MACRO0(RESTORE_SAVE_EVERYTHING_FRAME)
     // Restore FPRs. Method and padding is still on the stack.
     movsd 16(%esp), %xmm0
@@ -330,6 +320,7 @@
 MACRO2(ONE_ARG_RUNTIME_EXCEPTION, c_name, cxx_name)
     DEFINE_FUNCTION VAR(c_name)
     SETUP_SAVE_ALL_CALLEE_SAVES_FRAME ebx, ebx // save all registers as basis for long jump context
+    mov %esp, %ecx
     // Outgoing argument set up
     subl MACRO_LITERAL(8), %esp                // alignment padding
     CFI_ADJUST_CFA_OFFSET(8)
@@ -363,23 +354,7 @@
     /*
      * Call installed by a signal handler to create and deliver a NullPointerException.
      */
-DEFINE_FUNCTION_CUSTOM_CFA art_quick_throw_null_pointer_exception_from_signal, 2 * __SIZEOF_POINTER__
-    // Fault address and return address were saved by the fault handler.
-    // Save all registers as basis for long jump context; EDI will replace fault address later.
-    SETUP_SAVE_EVERYTHING_FRAME_EDI_SAVED ebx, ebx
-    // Retrieve fault address and save EDI.
-    movl (FRAME_SIZE_SAVE_EVERYTHING - 2 * __SIZEOF_POINTER__)(%esp), %eax
-    movl %edi, (FRAME_SIZE_SAVE_EVERYTHING - 2 * __SIZEOF_POINTER__)(%esp)
-    CFI_REL_OFFSET(%edi, (FRAME_SIZE_SAVE_EVERYTHING - 2 * __SIZEOF_POINTER__))
-    // Outgoing argument set up
-    subl MACRO_LITERAL(8), %esp                           // alignment padding
-    CFI_ADJUST_CFA_OFFSET(8)
-    pushl %fs:THREAD_SELF_OFFSET                          // pass Thread::Current()
-    CFI_ADJUST_CFA_OFFSET(4)
-    PUSH eax                                              // pass arg1
-    call SYMBOL(artThrowNullPointerExceptionFromSignal)   // (addr, self)
-    UNREACHABLE
-END_FUNCTION art_quick_throw_null_pointer_exception
+ONE_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception_from_signal, artThrowNullPointerExceptionFromSignal
 
     /*
      * Called by managed code to create and deliver an ArithmeticException.
diff --git a/runtime/arch/x86_64/asm_support_x86_64.S b/runtime/arch/x86_64/asm_support_x86_64.S
index af4a6c4..0728f99 100644
--- a/runtime/arch/x86_64/asm_support_x86_64.S
+++ b/runtime/arch/x86_64/asm_support_x86_64.S
@@ -110,7 +110,7 @@
 
 // TODO: we might need to use SYMBOL() here to add the underscore prefix
 // for mac builds.
-MACRO2(DEFINE_FUNCTION_CUSTOM_CFA, c_name, cfa_offset)
+MACRO1(DEFINE_FUNCTION, c_name)
     FUNCTION_TYPE(SYMBOL(\c_name))
     ASM_HIDDEN CALLVAR(c_name)
     .globl CALLVAR(c_name)
@@ -118,11 +118,7 @@
 CALLVAR(c_name):
     CFI_STARTPROC
     // Ensure we get a sane starting CFA.
-    CFI_DEF_CFA(rsp, RAW_VAR(cfa_offset))
-END_MACRO
-
-MACRO1(DEFINE_FUNCTION, c_name)
-    DEFINE_FUNCTION_CUSTOM_CFA RAW_VAR(c_name), __SIZEOF_POINTER__
+    CFI_DEF_CFA(rsp, 8)
 END_MACRO
 
 MACRO1(END_FUNCTION, c_name)
diff --git a/runtime/arch/x86_64/quick_entrypoints_x86_64.S b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
index 089ed75..5ea58af 100644
--- a/runtime/arch/x86_64/quick_entrypoints_x86_64.S
+++ b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
@@ -263,15 +263,14 @@
     /*
      * Macro that sets up the callee save frame to conform with
      * Runtime::CreateCalleeSaveMethod(kSaveEverything)
-     * when R15 is already saved.
      */
-MACRO0(SETUP_SAVE_EVERYTHING_FRAME_R15_SAVED)
+MACRO0(SETUP_SAVE_EVERYTHING_FRAME)
 #if defined(__APPLE__)
     int3
     int3
 #else
     // Save core registers from highest to lowest to agree with core spills bitmap.
-    // R15, or at least a placeholder for it, is already on the stack.
+    PUSH r15
     PUSH r14
     PUSH r13
     PUSH r12
@@ -323,15 +322,6 @@
 #endif  // __APPLE__
 END_MACRO
 
-    /*
-     * Macro that sets up the callee save frame to conform with
-     * Runtime::CreateCalleeSaveMethod(kSaveEverything)
-     */
-MACRO0(SETUP_SAVE_EVERYTHING_FRAME)
-    PUSH r15
-    SETUP_SAVE_EVERYTHING_FRAME_R15_SAVED
-END_MACRO
-
 MACRO0(RESTORE_SAVE_EVERYTHING_FRAME)
     // Restore FPRs. Method and padding is still on the stack.
     movq 16(%rsp), %xmm0
@@ -423,19 +413,7 @@
     /*
      * Call installed by a signal handler to create and deliver a NullPointerException.
      */
-DEFINE_FUNCTION_CUSTOM_CFA art_quick_throw_null_pointer_exception_from_signal, 2 * __SIZEOF_POINTER__
-    // Fault address and return address were saved by the fault handler.
-    // Save all registers as basis for long jump context; R15 will replace fault address later.
-    SETUP_SAVE_EVERYTHING_FRAME_R15_SAVED
-    // Retrieve fault address and save R15.
-    movq (FRAME_SIZE_SAVE_EVERYTHING - 2 * __SIZEOF_POINTER__)(%rsp), %rdi
-    movq %r15, (FRAME_SIZE_SAVE_EVERYTHING - 2 * __SIZEOF_POINTER__)(%rsp)
-    CFI_REL_OFFSET(%r15, (FRAME_SIZE_SAVE_EVERYTHING - 2 * __SIZEOF_POINTER__))
-    // Outgoing argument set up; RDI already contains the fault address.
-    movq %gs:THREAD_SELF_OFFSET, %rsi  // pass Thread::Current()
-    call SYMBOL(artThrowNullPointerExceptionFromSignal)  // (addr, self)
-    UNREACHABLE
-END_FUNCTION art_quick_throw_null_pointer_exception_from_signal
+ONE_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception_from_signal, artThrowNullPointerExceptionFromSignal
 
     /*
      * Called by managed code to create and deliver an ArithmeticException.
diff --git a/runtime/base/logging.cc b/runtime/base/logging.cc
index 529c391..e00e62d 100644
--- a/runtime/base/logging.cc
+++ b/runtime/base/logging.cc
@@ -187,7 +187,7 @@
 LogMessage::LogMessage(const char* file, unsigned int line, LogSeverity severity, int error)
   : data_(new LogMessageData(file, line, severity, error)) {
   if (PrintDirectly(severity)) {
-    static constexpr char kLogCharacters[] = { 'N', 'V', 'D', 'I', 'W', 'E', 'F', 'F' };
+    static constexpr char kLogCharacters[] = { 'V', 'D', 'I', 'W', 'E', 'F', 'F' };
     static_assert(arraysize(kLogCharacters) == static_cast<size_t>(INTERNAL_FATAL) + 1,
                   "Wrong character array size");
     stream() << ProgramInvocationShortName() << " " << kLogCharacters[static_cast<size_t>(severity)]
@@ -198,7 +198,7 @@
   if (PrintDirectly(data_->GetSeverity())) {
     // Add newline at the end to match the not printing directly behavior.
     std::cerr << '\n';
-  } else if (data_->GetSeverity() != LogSeverity::NONE) {
+  } else {
     if (data_->GetSeverity() < gMinimumLogSeverity) {
       return;  // No need to format something we're not going to output.
     }
@@ -242,7 +242,6 @@
 
 #ifdef ART_TARGET_ANDROID
 static const android_LogPriority kLogSeverityToAndroidLogPriority[] = {
-  ANDROID_LOG_VERBOSE,  // NONE, use verbose as stand-in, will never be printed.
   ANDROID_LOG_VERBOSE, ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN,
   ANDROID_LOG_ERROR, ANDROID_LOG_FATAL, ANDROID_LOG_FATAL
 };
@@ -252,10 +251,6 @@
 
 void LogMessage::LogLine(const char* file, unsigned int line, LogSeverity log_severity,
                          const char* message) {
-  if (log_severity == LogSeverity::NONE) {
-    return;
-  }
-
 #ifdef ART_TARGET_ANDROID
   const char* tag = ProgramInvocationShortName();
   int priority = kLogSeverityToAndroidLogPriority[static_cast<size_t>(log_severity)];
@@ -265,7 +260,7 @@
     LOG_PRI(priority, tag, "%s", message);
   }
 #else
-  static const char* log_characters = "NVDIWEFF";
+  static const char* log_characters = "VDIWEFF";
   CHECK_EQ(strlen(log_characters), INTERNAL_FATAL + 1U);
   char severity = log_characters[log_severity];
   fprintf(stderr, "%s %c %5d %5d %s:%u] %s\n",
@@ -275,10 +270,6 @@
 
 void LogMessage::LogLineLowStack(const char* file, unsigned int line, LogSeverity log_severity,
                                  const char* message) {
-  if (log_severity == LogSeverity::NONE) {
-    return;
-  }
-
 #ifdef ART_TARGET_ANDROID
   // Use android_writeLog() to avoid stack-based buffers used by android_printLog().
   const char* tag = ProgramInvocationShortName();
@@ -300,7 +291,7 @@
     android_writeLog(priority, tag, message);
   }
 #else
-  static constexpr char kLogCharacters[] = { 'N', 'V', 'D', 'I', 'W', 'E', 'F', 'F' };
+  static constexpr char kLogCharacters[] = { 'V', 'D', 'I', 'W', 'E', 'F', 'F' };
   static_assert(arraysize(kLogCharacters) == static_cast<size_t>(INTERNAL_FATAL) + 1,
                 "Wrong character array size");
 
diff --git a/runtime/base/logging.h b/runtime/base/logging.h
index f43cb8b..185aa0e 100644
--- a/runtime/base/logging.h
+++ b/runtime/base/logging.h
@@ -24,7 +24,6 @@
 namespace art {
 
 enum LogSeverity {
-  NONE,            // Fake level, don't log at all.
   VERBOSE,
   DEBUG,
   INFO,
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 8edb1b4..4d252e1 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -3848,7 +3848,9 @@
   return false;
 }
 
-void ClassLinker::VerifyClass(Thread* self, Handle<mirror::Class> klass, LogSeverity log_level) {
+void ClassLinker::VerifyClass(Thread* self,
+                              Handle<mirror::Class> klass,
+                              verifier::HardFailLogMode log_level) {
   {
     // TODO: assert that the monitor on the Class is held
     ObjectLock<mirror::Class> lock(self, klass);
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 4bd1bd2..5e4ae03 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -36,6 +36,7 @@
 #include "jni.h"
 #include "oat_file.h"
 #include "object_callbacks.h"
+#include "verifier/verifier_log_mode.h"
 
 namespace art {
 
@@ -460,7 +461,7 @@
 
   void VerifyClass(Thread* self,
                    Handle<mirror::Class> klass,
-                   LogSeverity log_level = LogSeverity::NONE)
+                   verifier::HardFailLogMode log_level = verifier::HardFailLogMode::kLogNone)
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!dex_lock_);
   bool VerifyClassUsingOatFile(const DexFile& dex_file,
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 3be39a1..5e0ee6f 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -697,6 +697,9 @@
 struct ExecutableOffsets : public CheckOffsets<mirror::Executable> {
   ExecutableOffsets() : CheckOffsets<mirror::Executable>(
       false, "Ljava/lang/reflect/Executable;") {
+    addOffset(OFFSETOF_MEMBER(mirror::Executable, has_real_parameter_data_),
+              "hasRealParameterData");
+    addOffset(OFFSETOF_MEMBER(mirror::Executable, parameters_), "parameters");
   };
 };
 
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index dba0a81..5bc4e88 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -591,9 +591,9 @@
   if (IsHost()) {
     const char* host_dir = getenv("ANDROID_HOST_OUT");
     CHECK(host_dir != nullptr);
-    location = StringPrintf("%s/framework/core.%s", host_dir, suffix);
+    location = StringPrintf("%s/framework/core-npic.%s", host_dir, suffix);
   } else {
-    location = StringPrintf("/data/art-test/core.%s", suffix);
+    location = StringPrintf("/data/art-test/core-npic.%s", suffix);
   }
 
   return location;
diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc
index ebadd79..76cd348 100644
--- a/runtime/dex_file.cc
+++ b/runtime/dex_file.cc
@@ -1431,6 +1431,34 @@
   return ProcessAnnotationSetRefList(method_class, set_ref_list, size);
 }
 
+mirror::Object* DexFile::GetAnnotationForMethodParameter(ArtMethod* method,
+                                                         uint32_t parameter_idx,
+                                                         Handle<mirror::Class> annotation_class)
+    const {
+  const ParameterAnnotationsItem* parameter_annotations = FindAnnotationsItemForMethod(method);
+  if (parameter_annotations == nullptr) {
+    return nullptr;
+  }
+  const AnnotationSetRefList* set_ref_list =
+      GetParameterAnnotationSetRefList(parameter_annotations);
+  if (set_ref_list == nullptr) {
+    return nullptr;
+  }
+
+  if (parameter_idx >= set_ref_list->size_) {
+    return nullptr;
+  }
+  const AnnotationSetRefItem* annotation_set_ref = &set_ref_list->list_[parameter_idx];
+  const AnnotationSetItem* annotation_set = GetSetRefItemItem(annotation_set_ref);
+
+  StackHandleScope<1> hs(Thread::Current());
+  Handle<mirror::Class> method_class(hs.NewHandle(method->GetDeclaringClass()));
+  return GetAnnotationObjectFromAnnotationSet(method_class,
+                                              annotation_set,
+                                              kDexVisibilityRuntime,
+                                              annotation_class);
+}
+
 mirror::ObjectArray<mirror::String>* DexFile::GetSignatureAnnotationForMethod(ArtMethod* method)
     const {
   const AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method);
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index ebbde0a..23676bd 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -953,6 +953,10 @@
       REQUIRES_SHARED(Locks::mutator_lock_);
   mirror::Object* GetAnnotationForMethod(ArtMethod* method, Handle<mirror::Class> annotation_class)
       const REQUIRES_SHARED(Locks::mutator_lock_);
+  mirror::Object* GetAnnotationForMethodParameter(ArtMethod* method,
+                                                  uint32_t parameter_idx,
+                                                  Handle<mirror::Class> annotation_class) const
+      REQUIRES_SHARED(Locks::mutator_lock_);
   mirror::ObjectArray<mirror::Object>* GetAnnotationsForMethod(ArtMethod* method) const
       REQUIRES_SHARED(Locks::mutator_lock_);
   mirror::ObjectArray<mirror::Class>* GetExceptionTypesForMethod(ArtMethod* method) const
diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc
index 975ac36..e534369 100644
--- a/runtime/gc/collector/concurrent_copying.cc
+++ b/runtime/gc/collector/concurrent_copying.cc
@@ -2087,7 +2087,8 @@
       to_ref = reinterpret_cast<mirror::Object*>(old_lock_word.ForwardingAddress());
       CHECK(to_ref != nullptr);
       CHECK_NE(to_ref, lost_fwd_ptr);
-      CHECK(region_space_->IsInToSpace(to_ref) || heap_->non_moving_space_->HasAddress(to_ref));
+      CHECK(region_space_->IsInToSpace(to_ref) || heap_->non_moving_space_->HasAddress(to_ref))
+          << "to_ref=" << to_ref << " " << heap_->DumpSpaces();
       CHECK_NE(to_ref->GetLockWord(false).GetState(), LockWord::kForwardingAddress);
       return to_ref;
     }
diff --git a/runtime/gc/collector_type.h b/runtime/gc/collector_type.h
index b342cc7..7014357 100644
--- a/runtime/gc/collector_type.h
+++ b/runtime/gc/collector_type.h
@@ -55,6 +55,8 @@
   kCollectorTypeClassLinker,
   // JIT Code cache fake collector.
   kCollectorTypeJitCodeCache,
+  // Fake collector for installing/removing a system-weak holder.
+  kCollectorTypeAddRemoveSystemWeakHolder,
 };
 std::ostream& operator<<(std::ostream& os, const CollectorType& collector_type);
 
diff --git a/runtime/gc/gc_cause.h b/runtime/gc/gc_cause.h
index 4348a41..f54f0e4 100644
--- a/runtime/gc/gc_cause.h
+++ b/runtime/gc/gc_cause.h
@@ -51,6 +51,8 @@
   kGcCauseClassLinker,
   // Not a real GC cause, used to implement exclusion between code cache metadata and GC.
   kGcCauseJitCodeCache,
+  // Not a real GC cause, used to add or remove system-weak holders.
+  kGcCauseAddRemoveSystemWeakHolder,
 };
 
 const char* PrettyCause(GcCause cause);
diff --git a/runtime/gc/system_weak.h b/runtime/gc/system_weak.h
new file mode 100644
index 0000000..3910a28
--- /dev/null
+++ b/runtime/gc/system_weak.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_GC_SYSTEM_WEAK_H_
+#define ART_RUNTIME_GC_SYSTEM_WEAK_H_
+
+#include "base/mutex.h"
+#include "object_callbacks.h"
+#include "thread-inl.h"
+
+namespace art {
+namespace gc {
+
+class AbstractSystemWeakHolder {
+ public:
+  virtual ~AbstractSystemWeakHolder() {}
+
+  virtual void Allow() REQUIRES_SHARED(Locks::mutator_lock_) = 0;
+  virtual void Disallow() REQUIRES_SHARED(Locks::mutator_lock_) = 0;
+  virtual void Broadcast() REQUIRES_SHARED(Locks::mutator_lock_) = 0;
+
+  virtual void Sweep(IsMarkedVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_) = 0;
+};
+
+class SystemWeakHolder : public AbstractSystemWeakHolder {
+ public:
+  explicit SystemWeakHolder(LockLevel level)
+      : allow_disallow_lock_("SystemWeakHolder", level),
+        new_weak_condition_("SystemWeakHolder new condition", allow_disallow_lock_),
+        allow_new_system_weak_(true) {
+  }
+  virtual ~SystemWeakHolder() {}
+
+  void Allow() OVERRIDE
+      REQUIRES_SHARED(Locks::mutator_lock_)
+      REQUIRES(!allow_disallow_lock_) {
+    CHECK(!kUseReadBarrier);
+    MutexLock mu(Thread::Current(), allow_disallow_lock_);
+    allow_new_system_weak_ = true;
+    new_weak_condition_.Broadcast(Thread::Current());
+  }
+
+  void Disallow() OVERRIDE
+      REQUIRES_SHARED(Locks::mutator_lock_)
+      REQUIRES(!allow_disallow_lock_) {
+    CHECK(!kUseReadBarrier);
+    MutexLock mu(Thread::Current(), allow_disallow_lock_);
+    allow_new_system_weak_ = false;
+  }
+
+  void Broadcast() OVERRIDE
+      REQUIRES_SHARED(Locks::mutator_lock_)
+      REQUIRES(!allow_disallow_lock_) {
+    CHECK(kUseReadBarrier);
+    MutexLock mu(Thread::Current(), allow_disallow_lock_);
+    new_weak_condition_.Broadcast(Thread::Current());
+  }
+
+ protected:
+  void Wait(Thread* self) REQUIRES_SHARED(allow_disallow_lock_) {
+    // Wait for GC's sweeping to complete and allow new records
+    while (UNLIKELY((!kUseReadBarrier && !allow_new_system_weak_) ||
+                    (kUseReadBarrier && !self->GetWeakRefAccessEnabled()))) {
+      new_weak_condition_.WaitHoldingLocks(self);
+    }
+  }
+
+  Mutex allow_disallow_lock_;
+  ConditionVariable new_weak_condition_ GUARDED_BY(allow_disallow_lock_);
+  bool allow_new_system_weak_ GUARDED_BY(allow_disallow_lock_);
+};
+
+}  // namespace gc
+}  // namespace art
+
+#endif  // ART_RUNTIME_GC_SYSTEM_WEAK_H_
diff --git a/runtime/gc/system_weak_test.cc b/runtime/gc/system_weak_test.cc
new file mode 100644
index 0000000..7c1ec8a
--- /dev/null
+++ b/runtime/gc/system_weak_test.cc
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "system_weak.h"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <memory>
+
+#include "base/mutex.h"
+#include "collector_type.h"
+#include "common_runtime_test.h"
+#include "handle_scope-inl.h"
+#include "heap.h"
+#include "mirror/string.h"
+#include "scoped_thread_state_change.h"
+#include "thread_list.h"
+
+namespace art {
+namespace gc {
+
+class SystemWeakTest : public CommonRuntimeTest {
+};
+
+struct CountingSystemWeakHolder : public SystemWeakHolder {
+  CountingSystemWeakHolder()
+      : SystemWeakHolder(kAllocTrackerLock),
+        allow_count_(0),
+        disallow_count_(0),
+        sweep_count_(0) {}
+
+  void Allow() OVERRIDE
+      REQUIRES_SHARED(Locks::mutator_lock_)
+      REQUIRES(!allow_disallow_lock_) {
+    SystemWeakHolder::Allow();
+
+    allow_count_++;
+  }
+
+  void Disallow() OVERRIDE
+      REQUIRES_SHARED(Locks::mutator_lock_)
+      REQUIRES(!allow_disallow_lock_) {
+    SystemWeakHolder::Disallow();
+
+    disallow_count_++;
+  }
+
+  void Broadcast() OVERRIDE
+      REQUIRES_SHARED(Locks::mutator_lock_)
+      REQUIRES(!allow_disallow_lock_) {
+    SystemWeakHolder::Broadcast();
+
+    allow_count_++;
+  }
+
+  void Sweep(IsMarkedVisitor* visitor) OVERRIDE
+      REQUIRES_SHARED(Locks::mutator_lock_)
+      REQUIRES(!allow_disallow_lock_) {
+    MutexLock mu(Thread::Current(), allow_disallow_lock_);
+    mirror::Object* old_object = weak_.Read<kWithoutReadBarrier>();
+    mirror::Object* new_object = old_object == nullptr ? nullptr : visitor->IsMarked(old_object);
+    weak_ = GcRoot<mirror::Object>(new_object);
+
+    sweep_count_++;
+  }
+
+  GcRoot<mirror::Object> Get()
+      REQUIRES_SHARED(Locks::mutator_lock_)
+      REQUIRES(!allow_disallow_lock_) {
+    Thread* self = Thread::Current();
+    MutexLock mu(self, allow_disallow_lock_);
+    Wait(self);
+
+    return weak_;
+  }
+
+  void Set(GcRoot<mirror::Object> obj)
+      REQUIRES_SHARED(Locks::mutator_lock_)
+      REQUIRES(!allow_disallow_lock_) {
+    Thread* self = Thread::Current();
+    MutexLock mu(self, allow_disallow_lock_);
+    Wait(self);
+
+    weak_ = obj;
+  }
+
+  size_t allow_count_;
+  size_t disallow_count_;
+  size_t sweep_count_;
+  GcRoot<mirror::Object> weak_ GUARDED_BY(allow_disallow_lock_);
+};
+
+static bool CollectorDoesAllowOrBroadcast() {
+  CollectorType type = Runtime::Current()->GetHeap()->CurrentCollectorType();
+  switch (type) {
+    case CollectorType::kCollectorTypeCMS:
+    case CollectorType::kCollectorTypeCC:
+      return true;
+
+    default:
+      return false;
+  }
+}
+
+static bool CollectorDoesDisallow() {
+  CollectorType type = Runtime::Current()->GetHeap()->CurrentCollectorType();
+  switch (type) {
+    case CollectorType::kCollectorTypeCMS:
+      return true;
+
+    default:
+      return false;
+  }
+}
+
+TEST_F(SystemWeakTest, Keep) {
+  CountingSystemWeakHolder cswh;
+  Runtime::Current()->AddSystemWeakHolder(&cswh);
+
+  ScopedObjectAccess soa(Thread::Current());
+
+  StackHandleScope<1> hs(soa.Self());
+
+  // We use Strings because they are very easy to allocate.
+  Handle<mirror::String> s(hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "ABC")));
+  cswh.Set(GcRoot<mirror::Object>(s.Get()));
+
+  // Trigger a GC.
+  Runtime::Current()->GetHeap()->CollectGarbage(false);
+
+  // Expect the holder to have been called.
+  EXPECT_EQ(CollectorDoesAllowOrBroadcast() ? 1U : 0U, cswh.allow_count_);
+  EXPECT_EQ(CollectorDoesDisallow() ? 1U : 0U, cswh.disallow_count_);
+  EXPECT_EQ(1U, cswh.sweep_count_);
+
+  // Expect the weak to not be cleared.
+  EXPECT_FALSE(cswh.Get().IsNull());
+  EXPECT_EQ(cswh.Get().Read(), s.Get());
+}
+
+TEST_F(SystemWeakTest, Discard) {
+  CountingSystemWeakHolder cswh;
+  Runtime::Current()->AddSystemWeakHolder(&cswh);
+
+  ScopedObjectAccess soa(Thread::Current());
+
+  cswh.Set(GcRoot<mirror::Object>(mirror::String::AllocFromModifiedUtf8(soa.Self(), "ABC")));
+
+  // Trigger a GC.
+  Runtime::Current()->GetHeap()->CollectGarbage(false);
+
+  // Expect the holder to have been called.
+  EXPECT_EQ(CollectorDoesAllowOrBroadcast() ? 1U : 0U, cswh.allow_count_);
+  EXPECT_EQ(CollectorDoesDisallow() ? 1U : 0U, cswh.disallow_count_);
+  EXPECT_EQ(1U, cswh.sweep_count_);
+
+  // Expect the weak to be cleared.
+  EXPECT_TRUE(cswh.Get().IsNull());
+}
+
+TEST_F(SystemWeakTest, Remove) {
+  CountingSystemWeakHolder cswh;
+  Runtime::Current()->AddSystemWeakHolder(&cswh);
+
+  ScopedObjectAccess soa(Thread::Current());
+
+  StackHandleScope<1> hs(soa.Self());
+
+  // We use Strings because they are very easy to allocate.
+  Handle<mirror::String> s(hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "ABC")));
+  cswh.Set(GcRoot<mirror::Object>(s.Get()));
+
+  // Trigger a GC.
+  Runtime::Current()->GetHeap()->CollectGarbage(false);
+
+  // Expect the holder to have been called.
+  ASSERT_EQ(CollectorDoesAllowOrBroadcast() ? 1U : 0U, cswh.allow_count_);
+  ASSERT_EQ(CollectorDoesDisallow() ? 1U : 0U, cswh.disallow_count_);
+  ASSERT_EQ(1U, cswh.sweep_count_);
+
+  // Expect the weak to not be cleared.
+  ASSERT_FALSE(cswh.Get().IsNull());
+  ASSERT_EQ(cswh.Get().Read(), s.Get());
+
+  // Remove the holder.
+  Runtime::Current()->RemoveSystemWeakHolder(&cswh);
+
+  // Trigger another GC.
+  Runtime::Current()->GetHeap()->CollectGarbage(false);
+
+  // Expectation: no change in the numbers.
+  EXPECT_EQ(CollectorDoesAllowOrBroadcast() ? 1U : 0U, cswh.allow_count_);
+  EXPECT_EQ(CollectorDoesDisallow() ? 1U : 0U, cswh.disallow_count_);
+  EXPECT_EQ(1U, cswh.sweep_count_);
+}
+
+}  // namespace gc
+}  // namespace art
diff --git a/runtime/mirror/abstract_method.h b/runtime/mirror/abstract_method.h
index 22a3ea8..9c20613 100644
--- a/runtime/mirror/abstract_method.h
+++ b/runtime/mirror/abstract_method.h
@@ -63,8 +63,8 @@
 
   HeapReference<mirror::Class> declaring_class_;
   HeapReference<mirror::Class> declaring_class_of_overridden_method_;
-  uint32_t access_flags_;
   uint64_t art_method_;
+  uint32_t access_flags_;
   uint32_t dex_method_index_;
 
   friend struct art::AbstractMethodOffsets;  // for verifying offset information
diff --git a/runtime/mirror/accessible_object.h b/runtime/mirror/accessible_object.h
index 1d934a8..2581ac2 100644
--- a/runtime/mirror/accessible_object.h
+++ b/runtime/mirror/accessible_object.h
@@ -47,9 +47,8 @@
 
  private:
   uint8_t flag_;
-  // Padding required for now since "packed" will cause reflect.Field fields to not be aligned
-  // otherwise.
-  uint8_t padding_[3];
+  // Padding required for correct alignment of subclasses like Executable, Field, etc.
+  uint8_t padding_[1];
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(AccessibleObject);
 };
diff --git a/runtime/mirror/executable.h b/runtime/mirror/executable.h
index 8786657..232fce8 100644
--- a/runtime/mirror/executable.h
+++ b/runtime/mirror/executable.h
@@ -33,6 +33,9 @@
 // C++ mirror of java.lang.reflect.Executable.
 class MANAGED Executable : public AccessibleObject {
  private:
+  uint16_t has_real_parameter_data_;
+  HeapReference<mirror::Array> parameters_;
+
   friend struct art::ExecutableOffsets;  // for verifying offset information
   DISALLOW_IMPLICIT_CONSTRUCTORS(Executable);
 };
diff --git a/runtime/mirror/field.h b/runtime/mirror/field.h
index 7eb9da4..f378568 100644
--- a/runtime/mirror/field.h
+++ b/runtime/mirror/field.h
@@ -99,6 +99,9 @@
       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
 
  private:
+  // Padding required for matching alignment with the Java peer.
+  uint8_t padding_[2];
+
   HeapReference<mirror::Class> declaring_class_;
   HeapReference<mirror::Class> type_;
   int32_t access_flags_;
diff --git a/runtime/native/java_lang_reflect_Parameter.cc b/runtime/native/java_lang_reflect_Parameter.cc
new file mode 100644
index 0000000..8fe3bb5
--- /dev/null
+++ b/runtime/native/java_lang_reflect_Parameter.cc
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "java_lang_reflect_Parameter.h"
+
+#include "art_method-inl.h"
+#include "common_throws.h"
+#include "dex_file-inl.h"
+#include "jni_internal.h"
+#include "scoped_fast_native_object_access.h"
+#include "utils.h"
+
+namespace art {
+
+static jobject Parameter_getAnnotationNative(JNIEnv* env,
+                                             jclass,
+                                             jobject javaMethod,
+                                             jint parameterIndex,
+                                             jclass annotationType) {
+  ScopedFastNativeObjectAccess soa(env);
+  if (UNLIKELY(javaMethod == nullptr)) {
+    ThrowNullPointerException("javaMethod == null");
+    return nullptr;
+  }
+
+  ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod);
+  if (method->IsProxyMethod()) {
+    return nullptr;
+  }
+
+  uint32_t parameter_count = method->GetParameterTypeList()->Size();
+  if (UNLIKELY(parameterIndex < 0 || static_cast<uint32_t>(parameterIndex) >= parameter_count)) {
+    ThrowIllegalArgumentException(
+        StringPrintf("Illegal parameterIndex %d for %s, parameter_count is %d",
+                     parameterIndex,
+                     PrettyMethod(method).c_str(),
+                     parameter_count).c_str());
+    return nullptr;
+  }
+
+  StackHandleScope<1> hs(soa.Self());
+  Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType)));
+  return soa.AddLocalReference<jobject>(
+      method->GetDexFile()->GetAnnotationForMethodParameter(method, parameterIndex, klass));
+}
+
+static JNINativeMethod gMethods[] = {
+  NATIVE_METHOD(Parameter,
+                getAnnotationNative,
+                "!(Ljava/lang/reflect/Executable;ILjava/lang/Class;)Ljava/lang/annotation/Annotation;"),
+};
+
+void register_java_lang_reflect_Parameter(JNIEnv* env) {
+  REGISTER_NATIVE_METHODS("java/lang/reflect/Parameter");
+}
+
+}  // namespace art
diff --git a/runtime/native/java_lang_reflect_Parameter.h b/runtime/native/java_lang_reflect_Parameter.h
new file mode 100644
index 0000000..f6322b1
--- /dev/null
+++ b/runtime/native/java_lang_reflect_Parameter.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_NATIVE_JAVA_LANG_REFLECT_PARAMETER_H_
+#define ART_RUNTIME_NATIVE_JAVA_LANG_REFLECT_PARAMETER_H_
+
+#include <jni.h>
+
+namespace art {
+
+void register_java_lang_reflect_Parameter(JNIEnv* env);
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_NATIVE_JAVA_LANG_REFLECT_PARAMETER_H_
diff --git a/runtime/openjdkjvmti/OpenjdkJvmTi.cc b/runtime/openjdkjvmti/OpenjdkJvmTi.cc
index 339c457..d3561c1 100644
--- a/runtime/openjdkjvmti/OpenjdkJvmTi.cc
+++ b/runtime/openjdkjvmti/OpenjdkJvmTi.cc
@@ -32,6 +32,7 @@
 #include <jni.h>
 #include "openjdkjvmti/jvmti.h"
 
+#include "art_jvmti.h"
 #include "gc_root-inl.h"
 #include "globals.h"
 #include "jni_env_ext-inl.h"
@@ -44,25 +45,6 @@
 
 namespace openjdkjvmti {
 
-extern const jvmtiInterface_1 gJvmtiInterface;
-
-// A structure that is a jvmtiEnv with additional information for the runtime.
-struct ArtJvmTiEnv : public jvmtiEnv {
-  art::JavaVMExt* art_vm;
-  void* local_data;
-
-  explicit ArtJvmTiEnv(art::JavaVMExt* runtime) : art_vm(runtime), local_data(nullptr) {
-    functions = &gJvmtiInterface;
-  }
-};
-
-// Macro and constexpr to make error values less annoying to write.
-#define ERR(e) JVMTI_ERROR_ ## e
-static constexpr jvmtiError OK = JVMTI_ERROR_NONE;
-
-// Special error code for unimplemented functions in JVMTI
-static constexpr jvmtiError ERR(NOT_IMPLEMENTED) = JVMTI_ERROR_NOT_AVAILABLE;
-
 class JvmtiFunctions {
  private:
   static bool IsValidEnv(jvmtiEnv* env) {
diff --git a/runtime/openjdkjvmti/art_jvmti.h b/runtime/openjdkjvmti/art_jvmti.h
new file mode 100644
index 0000000..a2c6882
--- /dev/null
+++ b/runtime/openjdkjvmti/art_jvmti.h
@@ -0,0 +1,74 @@
+/* Copyright (C) 2016 The Android Open Source Project
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This file implements interfaces from the file jvmti.h. This implementation
+ * is licensed under the same terms as the file jvmti.h.  The
+ * copyright and license information for the file jvmti.h follows.
+ *
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef ART_RUNTIME_OPENJDKJVMTI_ART_JVMTI_H_
+#define ART_RUNTIME_OPENJDKJVMTI_ART_JVMTI_H_
+
+#include <jni.h>
+
+#include "java_vm_ext.h"
+#include "jni_env_ext.h"
+#include "jvmti.h"
+
+namespace openjdkjvmti {
+
+extern const jvmtiInterface_1 gJvmtiInterface;
+
+// A structure that is a jvmtiEnv with additional information for the runtime.
+struct ArtJvmTiEnv : public jvmtiEnv {
+  art::JavaVMExt* art_vm;
+  void* local_data;
+
+  explicit ArtJvmTiEnv(art::JavaVMExt* runtime) : art_vm(runtime), local_data(nullptr) {
+    functions = &gJvmtiInterface;
+  }
+};
+
+// Macro and constexpr to make error values less annoying to write.
+#define ERR(e) JVMTI_ERROR_ ## e
+static constexpr jvmtiError OK = JVMTI_ERROR_NONE;
+
+// Special error code for unimplemented functions in JVMTI
+static constexpr jvmtiError ERR(NOT_IMPLEMENTED) = JVMTI_ERROR_NOT_AVAILABLE;
+
+static inline JNIEnv* GetJniEnv(jvmtiEnv* env) {
+  JNIEnv* ret_value = nullptr;
+  jint res = reinterpret_cast<ArtJvmTiEnv*>(env)->art_vm->GetEnv(
+      reinterpret_cast<void**>(&ret_value), JNI_VERSION_1_1);
+  if (res != JNI_OK) {
+    return nullptr;
+  }
+  return ret_value;
+}
+
+}  // namespace openjdkjvmti
+
+#endif  // ART_RUNTIME_OPENJDKJVMTI_ART_JVMTI_H_
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index d8e8573..97911d4 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -71,8 +71,10 @@
 #include "fault_handler.h"
 #include "gc/accounting/card_table-inl.h"
 #include "gc/heap.h"
+#include "gc/scoped_gc_critical_section.h"
 #include "gc/space/image_space.h"
 #include "gc/space/space-inl.h"
+#include "gc/system_weak.h"
 #include "handle_scope-inl.h"
 #include "image-inl.h"
 #include "instrumentation.h"
@@ -111,6 +113,7 @@
 #include "native/java_lang_reflect_Constructor.h"
 #include "native/java_lang_reflect_Field.h"
 #include "native/java_lang_reflect_Method.h"
+#include "native/java_lang_reflect_Parameter.h"
 #include "native/java_lang_reflect_Proxy.h"
 #include "native/java_util_concurrent_atomic_AtomicLong.h"
 #include "native/libcore_util_CharsetUtils.h"
@@ -473,6 +476,11 @@
   GetMonitorList()->SweepMonitorList(visitor);
   GetJavaVM()->SweepJniWeakGlobals(visitor);
   GetHeap()->SweepAllocationRecords(visitor);
+
+  // All other generic system-weak holders.
+  for (gc::AbstractSystemWeakHolder* holder : system_weak_holders_) {
+    holder->Sweep(visitor);
+  }
 }
 
 bool Runtime::ParseOptions(const RuntimeOptions& raw_options,
@@ -1418,6 +1426,7 @@
   register_java_lang_reflect_Constructor(env);
   register_java_lang_reflect_Field(env);
   register_java_lang_reflect_Method(env);
+  register_java_lang_reflect_Parameter(env);
   register_java_lang_reflect_Proxy(env);
   register_java_lang_ref_Reference(env);
   register_java_lang_String(env);
@@ -1722,6 +1731,11 @@
   intern_table_->ChangeWeakRootState(gc::kWeakRootStateNoReadsOrWrites);
   java_vm_->DisallowNewWeakGlobals();
   heap_->DisallowNewAllocationRecords();
+
+  // All other generic system-weak holders.
+  for (gc::AbstractSystemWeakHolder* holder : system_weak_holders_) {
+    holder->Disallow();
+  }
 }
 
 void Runtime::AllowNewSystemWeaks() {
@@ -1730,6 +1744,11 @@
   intern_table_->ChangeWeakRootState(gc::kWeakRootStateNormal);  // TODO: Do this in the sweeping.
   java_vm_->AllowNewWeakGlobals();
   heap_->AllowNewAllocationRecords();
+
+  // All other generic system-weak holders.
+  for (gc::AbstractSystemWeakHolder* holder : system_weak_holders_) {
+    holder->Allow();
+  }
 }
 
 void Runtime::BroadcastForNewSystemWeaks() {
@@ -1740,6 +1759,11 @@
   intern_table_->BroadcastForNewInterns();
   java_vm_->BroadcastForNewWeakGlobals();
   heap_->BroadcastForNewAllocationRecords();
+
+  // All other generic system-weak holders.
+  for (gc::AbstractSystemWeakHolder* holder : system_weak_holders_) {
+    holder->Broadcast();
+  }
 }
 
 void Runtime::SetInstructionSet(InstructionSet instruction_set) {
@@ -2084,4 +2108,21 @@
   return c_env_vector_.get();
 }
 
+void Runtime::AddSystemWeakHolder(gc::AbstractSystemWeakHolder* holder) {
+  gc::ScopedGCCriticalSection gcs(Thread::Current(),
+                                  gc::kGcCauseAddRemoveSystemWeakHolder,
+                                  gc::kCollectorTypeAddRemoveSystemWeakHolder);
+  system_weak_holders_.push_back(holder);
+}
+
+void Runtime::RemoveSystemWeakHolder(gc::AbstractSystemWeakHolder* holder) {
+  gc::ScopedGCCriticalSection gcs(Thread::Current(),
+                                  gc::kGcCauseAddRemoveSystemWeakHolder,
+                                  gc::kCollectorTypeAddRemoveSystemWeakHolder);
+  auto it = std::find(system_weak_holders_.begin(), system_weak_holders_.end(), holder);
+  if (it != system_weak_holders_.end()) {
+    system_weak_holders_.erase(it);
+  }
+}
+
 }  // namespace art
diff --git a/runtime/runtime.h b/runtime/runtime.h
index dc14c04..58068eb 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -43,6 +43,7 @@
 namespace art {
 
 namespace gc {
+  class AbstractSystemWeakHolder;
   class Heap;
   namespace collector {
     class GarbageCollector;
@@ -651,6 +652,9 @@
     return env_snapshot_.GetSnapshot();
   }
 
+  void AddSystemWeakHolder(gc::AbstractSystemWeakHolder* holder);
+  void RemoveSystemWeakHolder(gc::AbstractSystemWeakHolder* holder);
+
  private:
   static void InitPlatformSignalHandlers();
 
@@ -887,6 +891,9 @@
     DISALLOW_COPY_AND_ASSIGN(EnvSnapshot);
   } env_snapshot_;
 
+  // Generic system-weak holders.
+  std::vector<gc::AbstractSystemWeakHolder*> system_weak_holders_;
+
   DISALLOW_COPY_AND_ASSIGN(Runtime);
 };
 std::ostream& operator<<(std::ostream& os, const Runtime::CalleeSaveType& rhs);
diff --git a/runtime/thread.cc b/runtime/thread.cc
index dde3640..43ef1cb 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -2835,6 +2835,14 @@
       for (size_t i = 0; i < BitSizeOf<uint32_t>(); ++i) {
         if (register_mask & (1 << i)) {
           mirror::Object** ref_addr = reinterpret_cast<mirror::Object**>(GetGPRAddress(i));
+          if (kIsDebugBuild && ref_addr == nullptr) {
+            std::string thread_name;
+            GetThread()->GetThreadName(thread_name);
+            LOG(INTERNAL_FATAL) << "On thread " << thread_name;
+            DescribeStack(GetThread());
+            LOG(FATAL) << "Found an unsaved callee-save register " << i << " (null GPRAddress) "
+                       << "set in register_mask=" << register_mask << " at " << DescribeLocation();
+          }
           if (*ref_addr != nullptr) {
             visitor_(ref_addr, -1, this);
           }
diff --git a/runtime/vdex_file.cc b/runtime/vdex_file.cc
index 12bc451..a71578b 100644
--- a/runtime/vdex_file.cc
+++ b/runtime/vdex_file.cc
@@ -19,6 +19,7 @@
 #include <memory>
 
 #include "base/logging.h"
+#include "base/unix_file/fd_file.h"
 
 namespace art {
 
@@ -81,7 +82,7 @@
   }
 
   *error_msg = "Success";
-  return new VdexFile(vdex_file.release(), mmap.release());
+  return new VdexFile(mmap.release());
 }
 
 }  // namespace art
diff --git a/runtime/vdex_file.h b/runtime/vdex_file.h
index e381eb7..9215e52 100644
--- a/runtime/vdex_file.h
+++ b/runtime/vdex_file.h
@@ -21,7 +21,6 @@
 #include <string>
 
 #include "base/macros.h"
-#include "base/unix_file/fd_file.h"
 #include "mem_map.h"
 #include "os.h"
 
@@ -66,9 +65,8 @@
   size_t Size() const { return mmap_->Size(); }
 
  private:
-  VdexFile(File* file, MemMap* mmap) : file_(file), mmap_(mmap) {}
+  explicit VdexFile(MemMap* mmap) : mmap_(mmap) {}
 
-  std::unique_ptr<File> file_;
   std::unique_ptr<MemMap> mmap_;
 
   DISALLOW_COPY_AND_ASSIGN(VdexFile);
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 589e71c..6b1170b 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -123,7 +123,7 @@
                                                         mirror::Class* klass,
                                                         CompilerCallbacks* callbacks,
                                                         bool allow_soft_failures,
-                                                        LogSeverity log_level,
+                                                        HardFailLogMode log_level,
                                                         std::string* error) {
   if (klass->IsVerified()) {
     return kNoFailure;
@@ -196,7 +196,7 @@
                                                           Handle<mirror::ClassLoader> class_loader,
                                                           CompilerCallbacks* callbacks,
                                                           bool allow_soft_failures,
-                                                          LogSeverity log_level,
+                                                          HardFailLogMode log_level,
                                                           bool need_precise_constants,
                                                           std::string* error_string) {
   DCHECK(it != nullptr);
@@ -267,7 +267,7 @@
                                                         const DexFile::ClassDef& class_def,
                                                         CompilerCallbacks* callbacks,
                                                         bool allow_soft_failures,
-                                                        LogSeverity log_level,
+                                                        HardFailLogMode log_level,
                                                         std::string* error) {
   ScopedTrace trace(__FUNCTION__);
 
@@ -360,7 +360,7 @@
                                                          uint32_t method_access_flags,
                                                          CompilerCallbacks* callbacks,
                                                          bool allow_soft_failures,
-                                                         LogSeverity log_level,
+                                                         HardFailLogMode log_level,
                                                          bool need_precise_constants,
                                                          std::string* hard_failure_msg) {
   MethodVerifier::FailureData result;
@@ -420,11 +420,26 @@
     } else {
       CHECK(verifier.have_pending_hard_failure_);
       if (VLOG_IS_ON(verifier)) {
-        log_level = LogSeverity::VERBOSE;
+        log_level = std::max(HardFailLogMode::kLogVerbose, log_level);
       }
-      if (log_level > LogSeverity::VERBOSE) {
-        verifier.DumpFailures(LOG(log_level) << "Verification error in "
-                                             << PrettyMethod(method_idx, *dex_file) << "\n");
+      if (log_level >= HardFailLogMode::kLogVerbose) {
+        LogSeverity severity;
+        switch (log_level) {
+          case HardFailLogMode::kLogVerbose:
+            severity = LogSeverity::VERBOSE;
+            break;
+          case HardFailLogMode::kLogWarning:
+            severity = LogSeverity::WARNING;
+            break;
+          case HardFailLogMode::kLogInternalFatal:
+            severity = LogSeverity::INTERNAL_FATAL;
+            break;
+          default:
+            LOG(FATAL) << "Unsupported log-level " << static_cast<uint32_t>(log_level);
+            UNREACHABLE();
+        }
+        verifier.DumpFailures(LOG(severity) << "Verification error in "
+                                            << PrettyMethod(method_idx, *dex_file) << "\n");
       }
       if (hard_failure_msg != nullptr) {
         CHECK(!verifier.failure_messages_.empty());
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index d4e12f7..c4b1c6e 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -32,6 +32,7 @@
 #include "method_reference.h"
 #include "register_line.h"
 #include "reg_type_cache.h"
+#include "verifier_log_mode.h"
 
 namespace art {
 
@@ -152,7 +153,7 @@
                                  mirror::Class* klass,
                                  CompilerCallbacks* callbacks,
                                  bool allow_soft_failures,
-                                 LogSeverity log_level,
+                                 HardFailLogMode log_level,
                                  std::string* error)
       REQUIRES_SHARED(Locks::mutator_lock_);
   static FailureKind VerifyClass(Thread* self,
@@ -162,7 +163,7 @@
                                  const DexFile::ClassDef& class_def,
                                  CompilerCallbacks* callbacks,
                                  bool allow_soft_failures,
-                                 LogSeverity log_level,
+                                 HardFailLogMode log_level,
                                  std::string* error)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
@@ -336,7 +337,7 @@
                                    Handle<mirror::ClassLoader> class_loader,
                                    CompilerCallbacks* callbacks,
                                    bool allow_soft_failures,
-                                   LogSeverity log_level,
+                                   HardFailLogMode log_level,
                                    bool need_precise_constants,
                                    std::string* error_string)
       REQUIRES_SHARED(Locks::mutator_lock_);
@@ -362,7 +363,7 @@
                                   uint32_t method_access_flags,
                                   CompilerCallbacks* callbacks,
                                   bool allow_soft_failures,
-                                  LogSeverity log_level,
+                                  HardFailLogMode log_level,
                                   bool need_precise_constants,
                                   std::string* hard_failure_msg)
       REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/verifier/method_verifier_test.cc b/runtime/verifier/method_verifier_test.cc
index 4fd581d..646987a 100644
--- a/runtime/verifier/method_verifier_test.cc
+++ b/runtime/verifier/method_verifier_test.cc
@@ -23,6 +23,7 @@
 #include "common_runtime_test.h"
 #include "dex_file.h"
 #include "scoped_thread_state_change.h"
+#include "verifier_log_mode.h"
 
 namespace art {
 namespace verifier {
@@ -37,12 +38,8 @@
 
     // Verify the class
     std::string error_msg;
-    MethodVerifier::FailureKind failure = MethodVerifier::VerifyClass(self,
-                                                                      klass,
-                                                                      nullptr,
-                                                                      true,
-                                                                      LogSeverity::WARNING,
-                                                                      &error_msg);
+    MethodVerifier::FailureKind failure = MethodVerifier::VerifyClass(
+        self, klass, nullptr, true, HardFailLogMode::kLogWarning, &error_msg);
     ASSERT_TRUE(failure == MethodVerifier::kNoFailure) << error_msg;
   }
 
diff --git a/runtime/verifier/verifier_log_mode.h b/runtime/verifier/verifier_log_mode.h
new file mode 100644
index 0000000..3744b9b
--- /dev/null
+++ b/runtime/verifier/verifier_log_mode.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_VERIFIER_VERIFIER_LOG_MODE_H_
+#define ART_RUNTIME_VERIFIER_VERIFIER_LOG_MODE_H_
+
+namespace art {
+namespace verifier {
+
+enum class HardFailLogMode {
+  kLogNone,                               // Don't log hard failures at all.
+  kLogVerbose,                            // Log with severity VERBOSE.
+  kLogWarning,                            // Log with severity WARNING.
+  kLogInternalFatal,                      // Log with severity INTERNAL_FATAL
+};
+
+}  // namespace verifier
+}  // namespace art
+
+#endif  // ART_RUNTIME_VERIFIER_VERIFIER_LOG_MODE_H_
diff --git a/test/439-npe/expected.txt b/test/439-npe/expected.txt
index b4fd6bb..34855ee 100644
--- a/test/439-npe/expected.txt
+++ b/test/439-npe/expected.txt
@@ -52,73 +52,3 @@
 $opt$noinline$getBooleanElement
 $opt$noinline$getCharElement
 $opt$noinline$getShortElement
-i0=4
-i1=8
-i2=12
-i3=16
-i4=20
-i5=24
-i6=28
-i7=32
-i8=36
-i9=40
-i10=44
-i11=48
-i12=52
-i13=56
-i14=44
-i15=57
-l0=84
-l1=88
-l2=92
-l3=96
-l4=100
-l5=104
-l6=108
-l7=112
-l8=116
-l9=120
-l10=124
-l11=128
-l12=132
-l13=136
-l14=104
-l15=146
-f0=164.0
-f1=168.0
-f2=172.0
-f3=176.0
-f4=180.0
-f5=184.0
-f6=188.0
-f7=192.0
-f8=196.0
-f9=200.0
-f10=204.0
-f11=208.0
-f12=212.0
-f13=216.0
-f14=164.0
-f15=55.5
-d0=244.0
-d1=248.0
-d2=252.0
-d3=256.0
-d4=260.0
-d5=264.0
-d6=268.0
-d7=272.0
-d8=276.0
-d9=280.0
-d10=284.0
-d11=288.0
-d12=292.0
-d13=296.0
-d14=224.0
-d15=75.125
-addInt=42
-addLong=111
-addFloat=0.5
-addDouble=0.125
-m=null
-i=2
diff --git a/test/439-npe/src/Main.java b/test/439-npe/src/Main.java
index bc044a4..8f66da0 100644
--- a/test/439-npe/src/Main.java
+++ b/test/439-npe/src/Main.java
@@ -634,246 +634,12 @@
     } catch (NullPointerException npe) {
       check(npe, thisLine += 6, methodLine += 5, "$opt$noinline$getShortElement");
     }
-
-    $opt$noinline$testRegisterRetrieval();
   }
 
-  static void $opt$noinline$testRegisterRetrieval() {
-    Main[] array = $noinline$PrepareArray();
-    int i0 = 0;
-    int i1 = 1;
-    int i2 = 2;
-    int i3 = 3;
-    int i4 = 4;
-    int i5 = 5;
-    int i6 = 6;
-    int i7 = 7;
-    int i8 = 8;
-    int i9 = 9;
-    int i10 = 10;
-    int i11 = 11;
-    int i12 = 12;
-    int i13 = 13;
-    int i14 = 14;
-    int i15 = 15;
-    long l0 = 20L;
-    long l1 = 21L;
-    long l2 = 22L;
-    long l3 = 23L;
-    long l4 = 24L;
-    long l5 = 25L;
-    long l6 = 26L;
-    long l7 = 27L;
-    long l8 = 28L;
-    long l9 = 29L;
-    long l10 = 30L;
-    long l11 = 31L;
-    long l12 = 32L;
-    long l13 = 33L;
-    long l14 = 34L;
-    long l15 = 35L;
-    float f0 = 40.0f;
-    float f1 = 41.0f;
-    float f2 = 42.0f;
-    float f3 = 43.0f;
-    float f4 = 44.0f;
-    float f5 = 45.0f;
-    float f6 = 46.0f;
-    float f7 = 47.0f;
-    float f8 = 48.0f;
-    float f9 = 49.0f;
-    float f10 = 50.0f;
-    float f11 = 51.0f;
-    float f12 = 52.0f;
-    float f13 = 53.0f;
-    float f14 = 54.0f;
-    float f15 = 55.0f;
-    double d0 = 60.0;
-    double d1 = 61.0;
-    double d2 = 62.0;
-    double d3 = 63.0;
-    double d4 = 64.0;
-    double d5 = 65.0;
-    double d6 = 66.0;
-    double d7 = 67.0;
-    double d8 = 68.0;
-    double d9 = 69.0;
-    double d10 = 70.0;
-    double d11 = 71.0;
-    double d12 = 72.0;
-    double d13 = 73.0;
-    double d14 = 74.0;
-    double d15 = 75.0;
-    int addInt = -1;
-    long addLong = -2L;
-    float addFloat = -3.0f;
-    double addDouble = -4.0;
-    Main m = null;
-    int i = 0;
-    try {
-      for (i = 0; i < array.length; ++i) {
-        m = array[i];
-        // We have 16 ints, 16 longs, 16 floats, 16 doubles and a few helper variables here,
-        // none of them anonymous. Hopefully, all available physical registers will be allocated
-        // to these variables, so that when `m.intField` throws NPE during the third iteration,
-        // we will fully test retrieval of values from all physical registers.
-        addInt = m.intField;
-        addLong = m.longField;
-        addFloat = m.floatField;
-        addDouble = m.doubleField;
-        i0 += i1;
-        i1 += i2;
-        i2 += i3;
-        i3 += i4;
-        i4 += i5;
-        i5 += i6;
-        i6 += i7;
-        i7 += i8;
-        i8 += i9;
-        i9 += i10;
-        i10 += i11;
-        i11 += i12;
-        i12 += i13;
-        i13 += i14;
-        i14 += i15;
-        i15 += addInt;
-        l0 += l1;
-        l1 += l2;
-        l2 += l3;
-        l3 += l4;
-        l4 += l5;
-        l5 += l6;
-        l6 += l7;
-        l7 += l8;
-        l8 += l9;
-        l9 += l10;
-        l10 += l11;
-        l11 += l12;
-        l12 += l13;
-        l13 += l14;
-        l14 += l15;
-        l15 += addLong;
-        f0 += f1;
-        f1 += f2;
-        f2 += f3;
-        f3 += f4;
-        f4 += f5;
-        f5 += f6;
-        f6 += f7;
-        f7 += f8;
-        f8 += f9;
-        f9 += f10;
-        f10 += f11;
-        f11 += f12;
-        f12 += f13;
-        f13 += f14;
-        f14 += f15;
-        f15 += addFloat;
-        d0 += d1;
-        d1 += d2;
-        d2 += d3;
-        d3 += d4;
-        d4 += d5;
-        d5 += d6;
-        d6 += d7;
-        d7 += d8;
-        d8 += d9;
-        d9 += d10;
-        d10 += d11;
-        d11 += d12;
-        d12 += d13;
-        d13 += d14;
-        d14 += d15;
-        d15 += addDouble;
-      }
-    } catch (NullPointerException npe) {
-      System.out.println("i0=" + i0);
-      System.out.println("i1=" + i1);
-      System.out.println("i2=" + i2);
-      System.out.println("i3=" + i3);
-      System.out.println("i4=" + i4);
-      System.out.println("i5=" + i5);
-      System.out.println("i6=" + i6);
-      System.out.println("i7=" + i7);
-      System.out.println("i8=" + i8);
-      System.out.println("i9=" + i9);
-      System.out.println("i10=" + i10);
-      System.out.println("i11=" + i11);
-      System.out.println("i12=" + i12);
-      System.out.println("i13=" + i13);
-      System.out.println("i14=" + i14);
-      System.out.println("i15=" + i15);
-      System.out.println("l0=" + l0);
-      System.out.println("l1=" + l1);
-      System.out.println("l2=" + l2);
-      System.out.println("l3=" + l3);
-      System.out.println("l4=" + l4);
-      System.out.println("l5=" + l5);
-      System.out.println("l6=" + l6);
-      System.out.println("l7=" + l7);
-      System.out.println("l8=" + l8);
-      System.out.println("l9=" + l9);
-      System.out.println("l10=" + l10);
-      System.out.println("l11=" + l11);
-      System.out.println("l12=" + l12);
-      System.out.println("l13=" + l13);
-      System.out.println("l14=" + l14);
-      System.out.println("l15=" + l15);
-      System.out.println("f0=" + f0);
-      System.out.println("f1=" + f1);
-      System.out.println("f2=" + f2);
-      System.out.println("f3=" + f3);
-      System.out.println("f4=" + f4);
-      System.out.println("f5=" + f5);
-      System.out.println("f6=" + f6);
-      System.out.println("f7=" + f7);
-      System.out.println("f8=" + f8);
-      System.out.println("f9=" + f9);
-      System.out.println("f10=" + f10);
-      System.out.println("f11=" + f11);
-      System.out.println("f12=" + f12);
-      System.out.println("f13=" + f13);
-      System.out.println("f14=" + f14);
-      System.out.println("f15=" + f15);
-      System.out.println("d0=" + d0);
-      System.out.println("d1=" + d1);
-      System.out.println("d2=" + d2);
-      System.out.println("d3=" + d3);
-      System.out.println("d4=" + d4);
-      System.out.println("d5=" + d5);
-      System.out.println("d6=" + d6);
-      System.out.println("d7=" + d7);
-      System.out.println("d8=" + d8);
-      System.out.println("d9=" + d9);
-      System.out.println("d10=" + d10);
-      System.out.println("d11=" + d11);
-      System.out.println("d12=" + d12);
-      System.out.println("d13=" + d13);
-      System.out.println("d14=" + d14);
-      System.out.println("d15=" + d15);
-      System.out.println("addInt=" + addInt);
-      System.out.println("addLong=" + addLong);
-      System.out.println("addFloat=" + addFloat);
-      System.out.println("addDouble=" + addDouble);
-      System.out.println("m=" + m);
-      System.out.println("i=" + i);
-    }
-  }
-
-  static Main[] $noinline$PrepareArray() {
-    if (doThrow) { throw new Error(); }
-    Main[] array = new Main[] { new Main(), new Main(), null, new Main() };
-    array[1].intField = 42;
-    array[1].longField = 111L;
-    array[1].floatField = 0.5f;
-    array[1].doubleField = 0.125;
-    return array;
-  }
-
-  static void check(NullPointerException npe, int mainLine, int methodLine, String methodName) {
+  static void check(NullPointerException npe, int mainLine, int medthodLine, String methodName) {
     System.out.println(methodName);
     StackTraceElement[] trace = npe.getStackTrace();
-    checkElement(trace[0], "Main", methodName, "Main.java", methodLine);
+    checkElement(trace[0], "Main", methodName, "Main.java", medthodLine);
     checkElement(trace[1], "Main", "main", "Main.java", mainLine);
   }
 
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index d6957fc..e12fd28 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -153,17 +153,17 @@
 ifeq ($(ART_TEST_JNI_FORCECOPY),true)
   JNI_TYPES += forcecopy
 endif
-IMAGE_TYPES := image
+IMAGE_TYPES := picimage
 ifeq ($(ART_TEST_RUN_TEST_NO_IMAGE),true)
   IMAGE_TYPES += no-image
 endif
 ifeq ($(ART_TEST_RUN_TEST_MULTI_IMAGE),true)
-  IMAGE_TYPES := multiimage
+  IMAGE_TYPES := multipicimage
 endif
-ifeq ($(ART_TEST_PIC_IMAGE),true)
-  IMAGE_TYPES += picimage
+ifeq ($(ART_TEST_NPIC_IMAGE),true)
+  IMAGE_TYPES += npicimage
   ifeq ($(ART_TEST_RUN_TEST_MULTI_IMAGE),true)
-    IMAGE_TYPES := multipicimage
+    IMAGE_TYPES := multinpicimage
   endif
 endif
 PICTEST_TYPES := npictest
@@ -896,6 +896,11 @@
   ifeq ($(4),regalloc_gc)
     # Graph coloring tests share the image_suffix with optimizing tests.
     image_suffix := optimizing
+  else
+    ifeq ($(4),jit)
+      # JIT tests share the image_suffix with interpreter tests.
+      image_suffix := interpreter
+    endif
   endif
   ifeq ($(9),no-image)
     test_groups += ART_RUN_TEST_$$(uc_host_or_target)_NO_IMAGE_RULES
@@ -907,8 +912,9 @@
       prereq_rule += $$(TARGET_CORE_IMAGE_$$(image_suffix)_no-pic_$(13))
     endif
   else
-    ifeq ($(9),image)
+    ifeq ($(9),npicimage)
       test_groups += ART_RUN_TEST_$$(uc_host_or_target)_IMAGE_RULES
+      run_test_options += --npic-image
       # Add the core dependency.
       ifeq ($(1),host)
         prereq_rule += $$(HOST_CORE_IMAGE_$$(image_suffix)_no-pic_$(13))
@@ -918,16 +924,15 @@
     else
       ifeq ($(9),picimage)
         test_groups += ART_RUN_TEST_$$(uc_host_or_target)_PICIMAGE_RULES
-        run_test_options += --pic-image
         ifeq ($(1),host)
           prereq_rule += $$(HOST_CORE_IMAGE_$$(image_suffix)_pic_$(13))
         else
           prereq_rule += $$(TARGET_CORE_IMAGE_$$(image_suffix)_pic_$(13))
         endif
       else
-        ifeq ($(9),multiimage)
+        ifeq ($(9),multinpicimage)
           test_groups += ART_RUN_TEST_$$(uc_host_or_target)_IMAGE_RULES
-          run_test_options += --multi-image
+          run_test_options += --npic-image --multi-image
                 ifeq ($(1),host)
                         prereq_rule += $$(HOST_CORE_IMAGE_$$(image_suffix)_no-pic_multi_$(13))
                 else
@@ -936,7 +941,7 @@
         else
           ifeq ($(9),multipicimage)
             test_groups += ART_RUN_TEST_$$(uc_host_or_target)_PICIMAGE_RULES
-                        run_test_options += --pic-image --multi-image
+                        run_test_options += --multi-image
                         ifeq ($(1),host)
                         prereq_rule += $$(HOST_CORE_IMAGE_$$(image_suffix)_pic_multi_$(13))
                         else
diff --git a/test/run-test b/test/run-test
index 4c29420..8fb2adf 100755
--- a/test/run-test
+++ b/test/run-test
@@ -132,7 +132,7 @@
 android_root="/system"
 # By default we will use optimizing.
 image_args=""
-image_suffix="-optimizing"
+image_suffix=""
 
 while true; do
     if [ "x$1" = "x--host" ]; then
@@ -180,8 +180,8 @@
     elif [ "x$1" = "x--no-image" ]; then
         have_image="no"
         shift
-    elif [ "x$1" = "x--pic-image" ]; then
-        pic_image_suffix="-pic"
+    elif [ "x$1" = "x--npic-image" ]; then
+        pic_image_suffix="-npic"
         shift
     elif [ "x$1" = "x--multi-image" ]; then
         multi_image_suffix="-multi"
@@ -258,11 +258,10 @@
         shift
     elif [ "x$1" = "x--jit" ]; then
         image_args="--jit"
-        image_suffix="-jit"
+        image_suffix="-interpreter"
         shift
     elif [ "x$1" = "x--optimizing" ]; then
         image_args="-Xcompiler-option --compiler-backend=Optimizing"
-        image_suffix="-optimizing"
         shift
     elif [ "x$1" = "x--no-verify" ]; then
         run_args="${run_args} --no-verify"
@@ -608,8 +607,8 @@
         echo "    --dex2oat-swap        Use a dex2oat swap file."
         echo "    --instruction-set-features [string]"
         echo "                          Set instruction-set-features for compilation."
-        echo "    --pic-image           Use an image compiled with position independent code for the"
-        echo "                          boot class path."
+        echo "    --npic-image          Use an image compiled with non-position independent code "
+        echo "                          for the boot class path."
         echo "    --multi-image         Use a set of images compiled with dex2oat multi-image for"
         echo "                          the boot class path."
         echo "    --pic-test            Compile the test code position independent."
@@ -678,7 +677,7 @@
 # Tests named '<number>-checker-*' will also have their CFGs verified with
 # Checker when compiled with Optimizing on host.
 if [[ "$TEST_NAME" =~ ^[0-9]+-checker- ]]; then
-  if [ "$runtime" = "art" -a "$image_suffix" = "-optimizing" -a "$USE_JACK" = "true" ]; then
+  if [ "$runtime" = "art" -a "$image_suffix" = "" -a "$USE_JACK" = "true" ]; then
     # Optimizing has read barrier support for certain architectures
     # only. On other architectures, compiling is disabled when read
     # barriers are enabled, meaning that we do not produce a CFG file
diff --git a/tools/art b/tools/art
index 1a3bba7..1394a46 100644
--- a/tools/art
+++ b/tools/art
@@ -100,7 +100,7 @@
   $invoke_with $ANDROID_ROOT/bin/$DALVIKVM $lib \
     -XXlib:$LIBART \
     -Xnorelocate \
-    -Ximage:$ANDROID_ROOT/framework/core-optimizing-pic.art \
+    -Ximage:$ANDROID_ROOT/framework/core.art \
     $DEBUG_OPTION \
     "$@"
 
diff --git a/tools/buildbot-build.sh b/tools/buildbot-build.sh
index 12e0338..5ef66d1 100755
--- a/tools/buildbot-build.sh
+++ b/tools/buildbot-build.sh
@@ -45,6 +45,16 @@
   fi
 done
 
+# Workaround for repo incompatibilities on the Chromium buildbot.
+# TODO: Remove this workaround once https://bugs.chromium.org/p/chromium/issues/detail?id=646329
+# is addressed.
+repo=$(which repo)
+if [[ $repo == *"depot_tools"* ]]; then
+  ln -s build/soong/root.bp Android.bp
+  ln -s build/soong/bootstrap.bash bootstrap.bash
+  echo "include build/core/main.mk" > Makefile
+fi
+
 if [[ $mode == "host" ]]; then
   make_command="make $j_arg $showcommands build-art-host-tests $common_targets"
   make_command+=" ${out_dir}/host/linux-x86/lib/libjavacoretests.so "
diff --git a/tools/run-jdwp-tests.sh b/tools/run-jdwp-tests.sh
index 01dae43..74b0f16 100755
--- a/tools/run-jdwp-tests.sh
+++ b/tools/run-jdwp-tests.sh
@@ -43,7 +43,7 @@
 image_compiler_option=""
 debug="no"
 verbose="no"
-image="-Ximage:/data/art-test/core-optimizing-pic.art"
+image="-Ximage:/data/art-test/core.art"
 vm_args=""
 # By default, we run the whole JDWP test suite.
 test="org.apache.harmony.jpda.tests.share.AllTests"
diff --git a/tools/run-libcore-tests.sh b/tools/run-libcore-tests.sh
index 2a6e172..01c7f20 100755
--- a/tools/run-libcore-tests.sh
+++ b/tools/run-libcore-tests.sh
@@ -95,7 +95,7 @@
   if [[ "$1" == "--mode=device" ]]; then
     vogar_args="$vogar_args --device-dir=/data/local/tmp"
     vogar_args="$vogar_args --vm-command=/data/local/tmp/system/bin/art"
-    vogar_args="$vogar_args --vm-arg -Ximage:/data/art-test/core-optimizing.art"
+    vogar_args="$vogar_args --vm-arg -Ximage:/data/art-test/core.art"
     shift
   elif [[ "$1" == "--mode=host" ]]; then
     # We explicitly give a wrong path for the image, to ensure vogar