Merge "Revert "Revert^2 "JVMTI PopFrame support"""
diff --git a/.vpython b/.vpython
new file mode 100644
index 0000000..ed00723
--- /dev/null
+++ b/.vpython
@@ -0,0 +1,25 @@
+# This is a vpython "spec" file.
+#
+# It describes patterns for python wheel dependencies of the python scripts in
+# the chromium repo, particularly for dependencies that have compiled components
+# (since pure-python dependencies can be easily vendored into third_party).
+#
+# When vpython is invoked, it finds this file and builds a python VirtualEnv,
+# containing all of the dependencies described in this file, fetching them from
+# CIPD (the "Chrome Infrastructure Package Deployer" service). Unlike `pip`,
+# this never requires the end-user machine to have a working python extension
+# compilation environment. All of these packages are built using:
+#   https://chromium.googlesource.com/infra/infra/+/master/infra/tools/dockerbuild/
+#
+# All python scripts in the repo share this same spec, to avoid dependency
+# fragmentation.
+#
+# If you have depot_tools installed in your $PATH, you can invoke python scripts
+# in this repo by running them as you normally would run them, except
+# substituting `vpython` instead of `python` on the command line, e.g.:
+#   vpython path/to/script.py some --arguments
+#
+# Read more about `vpython` and how to modify this file here:
+#   https://chromium.googlesource.com/infra/infra/+/master/doc/users/vpython.md
+
+python_version: "2.7"
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index b97feff..c6fdf27 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -233,10 +233,10 @@
 
 ART_GTEST_dexoptanalyzer_test_HOST_DEPS := \
   $(ART_GTEST_dex2oat_environment_tests_HOST_DEPS) \
-  dexoptanalyzerd-host
+  $(HOST_OUT_EXECUTABLES)/dexoptanalyzerd
 ART_GTEST_dexoptanalyzer_test_TARGET_DEPS := \
   $(ART_GTEST_dex2oat_environment_tests_TARGET_DEPS) \
-  dexoptanalyzerd-target
+  $(TARGET_OUT_EXECUTABLES)/dexoptanalyzerd
 
 ART_GTEST_image_space_test_HOST_DEPS := \
   $(ART_GTEST_dex2oat_environment_tests_HOST_DEPS)
@@ -245,68 +245,68 @@
 
 ART_GTEST_dex2oat_test_HOST_DEPS := \
   $(ART_GTEST_dex2oat_environment_tests_HOST_DEPS) \
-  dex2oatd-host
+  $(HOST_OUT_EXECUTABLES)/dex2oatd
 ART_GTEST_dex2oat_test_TARGET_DEPS := \
   $(ART_GTEST_dex2oat_environment_tests_TARGET_DEPS) \
-  dex2oatd-target
+  $(TARGET_OUT_EXECUTABLES)/dex2oatd
 
 ART_GTEST_dex2oat_image_test_HOST_DEPS := \
   $(ART_GTEST_dex2oat_environment_tests_HOST_DEPS) \
-  dex2oatd-host
+  $(HOST_OUT_EXECUTABLES)/dex2oatd
 ART_GTEST_dex2oat_image_test_TARGET_DEPS := \
   $(ART_GTEST_dex2oat_environment_tests_TARGET_DEPS) \
-  dex2oatd-target
+  $(TARGET_OUT_EXECUTABLES)/dex2oatd
 
 # TODO: document why this is needed.
 ART_GTEST_proxy_test_HOST_DEPS := $(HOST_CORE_IMAGE_DEFAULT_64) $(HOST_CORE_IMAGE_DEFAULT_32)
 
 # The dexdiag test requires the dexdiag utility.
-ART_GTEST_dexdiag_test_HOST_DEPS := dexdiag-host
-ART_GTEST_dexdiag_test_TARGET_DEPS := dexdiag-target
+ART_GTEST_dexdiag_test_HOST_DEPS := $(HOST_OUT_EXECUTABLES)/dexdiag
+ART_GTEST_dexdiag_test_TARGET_DEPS := $(TARGET_OUT_EXECUTABLES)/dexdiag
 
 # 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_64) \
   $(HOST_CORE_IMAGE_DEFAULT_32) \
-  dexdump2-host
+  $(HOST_OUT_EXECUTABLES)/dexdump2
 ART_GTEST_dexdump_test_TARGET_DEPS := \
   $(TARGET_CORE_IMAGE_DEFAULT_64) \
   $(TARGET_CORE_IMAGE_DEFAULT_32) \
-  dexdump2-target
+  $(TARGET_OUT_EXECUTABLES)/dexdump2
 
 # The dexanalyze test requires an image and the dexanalyze utility.
 ART_GTEST_dexanalyze_test_HOST_DEPS := \
   $(HOST_CORE_IMAGE_DEFAULT_64) \
   $(HOST_CORE_IMAGE_DEFAULT_32) \
-  dexanalyze-host
+  $(HOST_OUT_EXECUTABLES)/dexanalyze
 ART_GTEST_dexanalyze_test_TARGET_DEPS := \
   $(TARGET_CORE_IMAGE_DEFAULT_64) \
   $(TARGET_CORE_IMAGE_DEFAULT_32) \
-  dexanalyze-target
+  $(TARGET_OUT_EXECUTABLES)/dexanalyze
 
 # 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_64) \
   $(HOST_CORE_IMAGE_DEFAULT_32) \
-  dexlayoutd-host \
-  dexdump2-host
+  $(HOST_OUT_EXECUTABLES)/dexlayoutd \
+  $(HOST_OUT_EXECUTABLES)/dexdump2
 ART_GTEST_dexlayout_test_TARGET_DEPS := \
   $(TARGET_CORE_IMAGE_DEFAULT_64) \
   $(TARGET_CORE_IMAGE_DEFAULT_32) \
-  dexlayoutd-target \
-  dexdump2-target
+  $(TARGET_OUT_EXECUTABLES)/dexlayoutd \
+  $(TARGET_OUT_EXECUTABLES)/dexdump2
 
 # The dexlist test requires an image and the dexlist utility.
 ART_GTEST_dexlist_test_HOST_DEPS := \
   $(HOST_CORE_IMAGE_DEFAULT_64) \
   $(HOST_CORE_IMAGE_DEFAULT_32) \
-  dexlist-host
+  $(HOST_OUT_EXECUTABLES)/dexlist
 ART_GTEST_dexlist_test_TARGET_DEPS := \
   $(TARGET_CORE_IMAGE_DEFAULT_64) \
   $(TARGET_CORE_IMAGE_DEFAULT_32) \
-  dexlist-target
+  $(TARGET_OUT_EXECUTABLES)/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
@@ -314,46 +314,46 @@
 ART_GTEST_imgdiag_test_HOST_DEPS := \
   $(HOST_CORE_IMAGE_DEFAULT_64) \
   $(HOST_CORE_IMAGE_DEFAULT_32) \
-  imgdiagd-host
+  $(HOST_OUT_EXECUTABLES)/imgdiagd
 ART_GTEST_imgdiag_test_TARGET_DEPS := \
   $(TARGET_CORE_IMAGE_DEFAULT_64) \
   $(TARGET_CORE_IMAGE_DEFAULT_32) \
-  imgdiagd-target
+  $(TARGET_OUT_EXECUTABLES)/imgdiagd
 
 # Dex analyze test requires dexanalyze.
 ART_GTEST_dexanalyze_test_HOST_DEPS := \
-  dexanalyze-host
+  $(HOST_OUT_EXECUTABLES)/dexanalyze
 ART_GTEST_dexanalyze_test_TARGET_DEPS := \
-  dexanalyze-target
+  $(TARGET_OUT_EXECUTABLES)/dexanalyze
 
 # Oatdump test requires an image and oatfile to dump.
 ART_GTEST_oatdump_test_HOST_DEPS := \
   $(HOST_CORE_IMAGE_DEFAULT_64) \
   $(HOST_CORE_IMAGE_DEFAULT_32) \
-  oatdumpd-host \
-  oatdumpds-host \
-  dexdump2-host
+  $(HOST_OUT_EXECUTABLES)/oatdumpd \
+  $(HOST_OUT_EXECUTABLES)/oatdumpds \
+  $(HOST_OUT_EXECUTABLES)/dexdump2
 ART_GTEST_oatdump_test_TARGET_DEPS := \
   $(TARGET_CORE_IMAGE_DEFAULT_64) \
   $(TARGET_CORE_IMAGE_DEFAULT_32) \
-  oatdumpd-target \
-  dexdump2-target
+  $(TARGET_OUT_EXECUTABLES)/oatdumpd \
+  $(TARGET_OUT_EXECUTABLES)/dexdump2
 ART_GTEST_oatdump_image_test_HOST_DEPS := $(ART_GTEST_oatdump_test_HOST_DEPS)
 ART_GTEST_oatdump_image_test_TARGET_DEPS := $(ART_GTEST_oatdump_test_TARGET_DEPS)
 ART_GTEST_oatdump_app_test_HOST_DEPS := $(ART_GTEST_oatdump_test_HOST_DEPS) \
-  dex2oatd-host \
-  dex2oatds-host
+  $(HOST_OUT_EXECUTABLES)/dex2oatd \
+  $(HOST_OUT_EXECUTABLES)/dex2oatds
 ART_GTEST_oatdump_app_test_TARGET_DEPS := $(ART_GTEST_oatdump_test_TARGET_DEPS) \
-  dex2oatd-target
+  $(TARGET_OUT_EXECUTABLES)/dex2oatd
 
 # Profile assistant tests requires profman utility.
-ART_GTEST_profile_assistant_test_HOST_DEPS := profmand-host
-ART_GTEST_profile_assistant_test_TARGET_DEPS := profmand-target
+ART_GTEST_profile_assistant_test_HOST_DEPS := $(HOST_OUT_EXECUTABLES)/profmand
+ART_GTEST_profile_assistant_test_TARGET_DEPS := $(TARGET_OUT_EXECUTABLES)/profmand
 
 ART_GTEST_hiddenapi_test_HOST_DEPS := \
   $(HOST_CORE_IMAGE_DEFAULT_64) \
   $(HOST_CORE_IMAGE_DEFAULT_32) \
-  hiddenapid-host
+  $(HOST_OUT_EXECUTABLES)/hiddenapid
 
 # The path for which all the source files are relative, not actually the current directory.
 LOCAL_PATH := art
@@ -482,7 +482,10 @@
 # $(2): path relative to $OUT to the test binary
 # $(3): 2ND_ or undefined - used to differentiate between the primary and secondary architecture.
 define define-art-gtest-rule-host
-  gtest_rule := test-art-host-gtest-$(1)$$($(3)ART_PHONY_TEST_HOST_SUFFIX)
+  gtest_suffix := $(1)$$($(3)ART_PHONY_TEST_HOST_SUFFIX)
+  gtest_rule := test-art-host-gtest-$$(gtest_suffix)
+  gtest_output := $(call intermediates-dir-for,PACKAGING,art-host-gtest,HOST)/$$(gtest_suffix).xml
+  $$(call dist-for-goals,$$(gtest_rule),$$(gtest_output):gtest/$$(gtest_suffix))
   gtest_exe := $(OUT_DIR)/$(2)
   # Dependencies for all host gtests.
   gtest_deps := $$(HOST_CORE_DEX_LOCATIONS) \
@@ -491,20 +494,20 @@
     $$(gtest_exe) \
     $$(ART_GTEST_$(1)_HOST_DEPS) \
     $(foreach file,$(ART_GTEST_$(1)_DEX_DEPS),$(ART_TEST_HOST_GTEST_$(file)_DEX))
-  ifneq (,$(DIST_DIR))
-    gtest_xml_output := --gtest_output=xml:$(DIST_DIR)/gtest/$(1)$$($(3)ART_PHONY_TEST_HOST_SUFFIX).xml
-  else
-    gtest_xml_output :=
-  endif
 
   ART_TEST_HOST_GTEST_DEPENDENCIES += $$(gtest_deps)
 
 .PHONY: $$(gtest_rule)
+$$(gtest_rule): $$(gtest_output)
+
+# Re-run the tests, even if nothing changed. Until the build system has a dedicated "no cache"
+# option, claim to write a file that is never produced.
+$$(gtest_output): .KATI_IMPLICIT_OUTPUTS := $$(gtest_output)-nocache
+$$(gtest_output): NAME := $$(gtest_rule)
 ifeq (,$(SANITIZE_HOST))
-$$(gtest_rule): PRIVATE_XML_OUTPUT := $$(gtest_xml_output)
-$$(gtest_rule): $$(gtest_exe) $$(gtest_deps)
-	$(hide) ($$(call ART_TEST_SKIP,$$@) && $$< $$(PRIVATE_XML_OUTPUT) && \
-		$$(call ART_TEST_PASSED,$$@)) || $$(call ART_TEST_FAILED,$$@)
+$$(gtest_output): $$(gtest_exe) $$(gtest_deps)
+	$(hide) ($$(call ART_TEST_SKIP,$$(NAME)) && $$< --gtest_output=xml:$$@ && \
+		$$(call ART_TEST_PASSED,$$(NAME))) || $$(call ART_TEST_FAILED,$$(NAME))
 else
 # Note: envsetup currently exports ASAN_OPTIONS=detect_leaks=0 to suppress leak detection, as some
 #       build tools (e.g., ninja) intentionally leak. We want leak checks when we run our tests, so
@@ -513,14 +516,13 @@
 # (with the x86-64 ABI, as this allows symbolization of both x86 and x86-64). We don't do this in
 # general as it loses all the color output, and we have our own symbolization step when not running
 # under ASAN.
-$$(gtest_rule): PRIVATE_XML_OUTPUT := $$(gtest_xml_output)
-$$(gtest_rule): $$(gtest_exe) $$(gtest_deps)
-	$(hide) ($$(call ART_TEST_SKIP,$$@) && set -o pipefail && \
-		ASAN_OPTIONS=detect_leaks=1 $$< $$(PRIVATE_XML_OUTPUT) 2>&1 | tee $$<.tmp.out >&2 && \
-		{ $$(call ART_TEST_PASSED,$$@) ; rm $$<.tmp.out ; }) || \
+$$(gtest_output): $$(gtest_exe) $$(gtest_deps)
+	$(hide) ($$(call ART_TEST_SKIP,$$(NAME)) && set -o pipefail && \
+		ASAN_OPTIONS=detect_leaks=1 $$< --gtest_output=xml:$$@ 2>&1 | tee $$<.tmp.out >&2 && \
+		{ $$(call ART_TEST_PASSED,$$(NAME)) ; rm $$<.tmp.out ; }) || \
 		( grep -q AddressSanitizer $$<.tmp.out && export ANDROID_BUILD_TOP=`pwd` && \
 			{ echo "ABI: 'x86_64'" | cat - $$<.tmp.out | development/scripts/stack | tail -n 3000 ; } ; \
-		rm $$<.tmp.out ; $$(call ART_TEST_FAILED,$$@))
+		rm $$<.tmp.out ; $$(call ART_TEST_FAILED,$$(NAME)))
 endif
 
   ART_TEST_HOST_GTEST$$($(3)ART_PHONY_TEST_HOST_SUFFIX)_RULES += $$(gtest_rule)
@@ -531,7 +533,9 @@
   # Clear locally defined variables.
   gtest_deps :=
   gtest_exe :=
+  gtest_output :=
   gtest_rule :=
+  gtest_suffix :=
 endef  # define-art-gtest-rule-host
 
 # Define the rules to build and run host and target gtests.
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index b4aa327..690802b 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -1010,25 +1010,6 @@
 
     base_img = base_img.substr(0, last_img_slash + 1);
 
-    // Note: we have some special case here for our testing. We have to inject the differentiating
-    //       parts for the different core images.
-    std::string infix;  // Empty infix by default.
-    {
-      // Check the first name.
-      std::string dex_file = oat_filenames_[0];
-      size_t last_dex_slash = dex_file.rfind('/');
-      if (last_dex_slash != std::string::npos) {
-        dex_file = dex_file.substr(last_dex_slash + 1);
-      }
-      size_t last_dex_dot = dex_file.rfind('.');
-      if (last_dex_dot != std::string::npos) {
-        dex_file = dex_file.substr(0, last_dex_dot);
-      }
-      if (android::base::StartsWith(dex_file, "core-")) {
-        infix = dex_file.substr(strlen("core"));
-      }
-    }
-
     std::string base_symbol_oat;
     if (!oat_unstripped_.empty()) {
       base_symbol_oat = oat_unstripped_[0];
@@ -1042,11 +1023,11 @@
     // Now create the other names. Use a counted loop to skip the first one.
     for (size_t i = 1; i < dex_locations_.size(); ++i) {
       // TODO: Make everything properly std::string.
-      std::string image_name = CreateMultiImageName(dex_locations_[i], prefix, infix, ".art");
+      std::string image_name = CreateMultiImageName(dex_locations_[i], prefix, ".art");
       char_backing_storage_.push_front(base_img + image_name);
       image_filenames_.push_back(char_backing_storage_.front().c_str());
 
-      std::string oat_name = CreateMultiImageName(dex_locations_[i], prefix, infix, ".oat");
+      std::string oat_name = CreateMultiImageName(dex_locations_[i], prefix, ".oat");
       char_backing_storage_.push_front(base_oat + oat_name);
       oat_filenames_.push_back(char_backing_storage_.front().c_str());
 
@@ -1061,11 +1042,9 @@
   //   0) Assume input is /a/b/c.d
   //   1) Strip the path  -> c.d
   //   2) Inject prefix p -> pc.d
-  //   3) Inject infix i  -> pci.d
-  //   4) Replace suffix with s if it's "jar"  -> d == "jar" -> pci.s
+  //   3) Replace suffix with s if it's "jar"  -> d == "jar" -> pc.s
   static std::string CreateMultiImageName(std::string in,
                                           const std::string& prefix,
-                                          const std::string& infix,
                                           const char* replace_suffix) {
     size_t last_dex_slash = in.rfind('/');
     if (last_dex_slash != std::string::npos) {
@@ -1074,13 +1053,6 @@
     if (!prefix.empty()) {
       in = prefix + in;
     }
-    if (!infix.empty()) {
-      // Inject infix.
-      size_t last_dot = in.rfind('.');
-      if (last_dot != std::string::npos) {
-        in.insert(last_dot, infix);
-      }
-    }
     if (android::base::EndsWith(in, ".jar")) {
       in = in.substr(0, in.length() - strlen(".jar")) +
           (replace_suffix != nullptr ? replace_suffix : "");
diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc
index 901f478..1e24f46 100644
--- a/dex2oat/linker/image_writer.cc
+++ b/dex2oat/linker/image_writer.cc
@@ -255,7 +255,7 @@
   }
 
   // Obtain class count for debugging purposes
-  if (kIsDebugBuild && compile_app_image_) {
+  if (VLOG_IS_ON(compiler) && compile_app_image_) {
     ScopedObjectAccess soa(self);
 
     size_t app_image_class_count  = 0;
@@ -272,7 +272,7 @@
       });
     }
 
-    LOG(INFO) << "Dex2Oat:AppImage:classCount = " << app_image_class_count;
+    VLOG(compiler) << "Dex2Oat:AppImage:classCount = " << app_image_class_count;
   }
 
   if (ClassLinker::kAppImageMayContainStrings && compile_app_image_) {
@@ -316,9 +316,9 @@
     CHECK_EQ(image_infos_.back().num_string_references_,
              string_reference_offsets_.size());
 
-    LOG(INFO) << "Dex2Oat:AppImage:stringReferences = " << string_reference_offsets_.size();
-    LOG(INFO) << "Dex2Oat:AppImage:managedStringReferences = " << managed_string_refs;
-    LOG(INFO) << "Dex2Oat:AppImage:nativeStringReferences = " << native_string_refs;
+    VLOG(compiler) << "Dex2Oat:AppImage:stringReferences = " << string_reference_offsets_.size();
+    VLOG(compiler) << "Dex2Oat:AppImage:managedStringReferences = " << managed_string_refs;
+    VLOG(compiler) << "Dex2Oat:AppImage:nativeStringReferences = " << native_string_refs;
   }
 
   // This needs to happen after CalculateNewObjectOffsets since it relies on intern_table_bytes_ and
@@ -706,7 +706,7 @@
       return false;
     }
 
-    if (kIsDebugBuild) {
+    if (VLOG_IS_ON(compiler)) {
       size_t separately_written_section_size = bitmap_section.Size() +
                                                image_header->GetImageRelocationsSection().Size() +
                                                sizeof(ImageHeader);
@@ -714,9 +714,9 @@
       size_t total_uncompressed_size = raw_image_data.size() + separately_written_section_size,
              total_compressed_size   = image_data.size() + separately_written_section_size;
 
-      LOG(INFO) << "Dex2Oat:uncompressedImageSize = " << total_uncompressed_size;
+      VLOG(compiler) << "Dex2Oat:uncompressedImageSize = " << total_uncompressed_size;
       if (total_uncompressed_size != total_compressed_size) {
-        LOG(INFO) << "Dex2Oat:compressedImageSize = " << total_compressed_size;
+        VLOG(compiler) << "Dex2Oat:compressedImageSize = " << total_compressed_size;
       }
     }
 
diff --git a/runtime/class_loader_context.cc b/runtime/class_loader_context.cc
index f6b764d..832f1d7 100644
--- a/runtime/class_loader_context.cc
+++ b/runtime/class_loader_context.cc
@@ -122,7 +122,7 @@
         return false;
       }
       uint32_t checksum = 0;
-      if (!android::base::ParseInt(dex_file_with_checksum[1].c_str(), &checksum)) {
+      if (!android::base::ParseUint(dex_file_with_checksum[1].c_str(), &checksum)) {
         return false;
       }
       class_loader_chain_.back().classpath.push_back(dex_file_with_checksum[0]);
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 19e14b9..fa36835 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -2084,15 +2084,12 @@
     size_t total_size =
         dchecked_integral_cast<size_t>(oat_end - image_start) + extra_reservation_size;
     bool relocate = Runtime::Current()->ShouldRelocate();
-    // If relocating, choose a random address for ALSR. Since mmap() does not randomize
-    // on its own, over-allocate and select a sub-region at a random offset.
-    size_t randomize_size = relocate
-        ? RoundUp(ART_BASE_ADDRESS_MAX_DELTA - ART_BASE_ADDRESS_MIN_DELTA, kPageSize) + kPageSize
-        : 0u;
+    // If relocating, choose a random address for ALSR.
+    uint32_t addr = relocate ? ART_BASE_ADDRESS + ChooseRelocationOffsetDelta() : image_start;
     *image_reservation =
         MemMap::MapAnonymous("Boot image reservation",
-                             relocate ? nullptr : reinterpret_cast32<uint8_t*>(image_start),
-                             total_size + randomize_size,
+                             reinterpret_cast32<uint8_t*>(addr),
+                             total_size,
                              PROT_NONE,
                              /* low_4gb= */ true,
                              /* reuse= */ false,
@@ -2101,17 +2098,6 @@
     if (!image_reservation->IsValid()) {
       return false;
     }
-    if (relocate) {
-      uint32_t offset = RoundDown(GetRandomNumber<uint32_t>(0u, randomize_size), kPageSize);
-      if (offset != 0u) {
-        MemMap unmapped_head = image_reservation->TakeReservedMemory(offset);
-        // Let the destructor of `unmapped_head` unmap the memory before the chunk we shall use.
-      }
-      DCHECK_LE(total_size, image_reservation->Size());
-      MemMap tmp = image_reservation->TakeReservedMemory(total_size);
-      tmp.swap(*image_reservation);
-      // Let the destructor of `tmp` unmap the memory after the chunk we shall use.
-    }
     DCHECK(!extra_reservation->IsValid());
     if (extra_reservation_size != 0u) {
       DCHECK_ALIGNED(extra_reservation_size, kPageSize);
@@ -2392,6 +2378,12 @@
   DCHECK_GT(oat_filenames.size(), 1u);
   // If the image filename was adapted (e.g., for our tests), we need to change this here,
   // too, but need to strip all path components (they will be re-established when loading).
+  // For example, dex location
+  //    /system/framework/core-libart.art
+  // with image name
+  //    out/target/product/taimen/dex_bootjars/system/framework/arm64/boot-core-libart.art
+  // yields boot class path component
+  //    /system/framework/boot-core-libart.art .
   std::ostringstream bootcp_oss;
   bool first_bootcp = true;
   for (size_t i = 0; i < dex_locations.size(); ++i) {
@@ -2411,7 +2403,7 @@
     size_t image_last_sep = (image_last_slash == std::string::npos)
                                 ? image_last_at
                                 : (image_last_at == std::string::npos)
-                                      ? std::string::npos
+                                      ? image_last_slash
                                       : std::max(image_last_slash, image_last_at);
     // Note: whenever image_last_sep == npos, +1 overflow means using the full string.
 
diff --git a/runtime/gc/space/region_space.cc b/runtime/gc/space/region_space.cc
index 171af6f..eba6fac 100644
--- a/runtime/gc/space/region_space.cc
+++ b/runtime/gc/space/region_space.cc
@@ -31,8 +31,7 @@
 static constexpr uint kEvacuateLivePercentThreshold = 75U;
 
 // Whether we protect the unused and cleared regions.
-// Only protect for target builds to prevent flaky test failures (b/63131961).
-static constexpr bool kProtectClearedRegions = kIsTargetBuild;
+static constexpr bool kProtectClearedRegions = true;
 
 // Wether we poison memory areas occupied by dead objects in unevacuated regions.
 static constexpr bool kPoisonDeadObjectsInUnevacuatedRegions = true;
@@ -70,6 +69,7 @@
   if (!mem_map.IsValid()) {
     LOG(ERROR) << "Failed to allocate pages for alloc space (" << name << ") of size "
         << PrettySize(capacity) << " with message " << error_msg;
+    PrintFileToLog("/proc/self/maps", LogSeverity::ERROR);
     MemMap::DumpMaps(LOG_STREAM(ERROR));
     return MemMap::Invalid();
   }
diff --git a/runtime/hprof/hprof.cc b/runtime/hprof/hprof.cc
index 9467c4c..f696e25 100644
--- a/runtime/hprof/hprof.cc
+++ b/runtime/hprof/hprof.cc
@@ -1073,7 +1073,8 @@
   if (obj->IsClass() && obj->AsClass()->IsRetired()) {
     return;
   }
-  DCHECK(visited_objects_.insert(obj).second) << "Already visited " << obj;
+  DCHECK(visited_objects_.insert(obj).second)
+      << "Already visited " << obj << "(" << obj->PrettyTypeOf() << ")";
 
   ++total_objects_;
 
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 92d4731..6577726 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -584,10 +584,10 @@
   for (uint32_t i = 0, e = shadow_frame->NumberOfVRegs(); i < e; ++i) {
     if (shadow_frame->GetVRegReference(i) == existing) {
       DCHECK_EQ(shadow_frame->GetVRegReference(i),
-                reinterpret_cast<mirror::Object*>(shadow_frame->GetVReg(i)));
+                reinterpret_cast<mirror::Object*>(static_cast<uint32_t>(shadow_frame->GetVReg(i))));
       shadow_frame->SetVRegReference(i, result.GetL());
       DCHECK_EQ(shadow_frame->GetVRegReference(i),
-                reinterpret_cast<mirror::Object*>(shadow_frame->GetVReg(i)));
+                reinterpret_cast<mirror::Object*>(static_cast<uint32_t>(shadow_frame->GetVReg(i))));
     }
   }
 }
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 4a3d8cb..0092b97 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -3422,45 +3422,37 @@
   return result;
 }
 
-// Note: this visitor may return with a method set, but dex_pc_ being DexFile:kDexNoIndex. This is
-//       so we don't abort in a special situation (thinlocked monitor) when dumping the Java stack.
-struct CurrentMethodVisitor final : public StackVisitor {
-  CurrentMethodVisitor(Thread* thread, Context* context, bool check_suspended, bool abort_on_error)
-      REQUIRES_SHARED(Locks::mutator_lock_)
-      : StackVisitor(thread,
-                     context,
-                     StackVisitor::StackWalkKind::kIncludeInlinedFrames,
-                     check_suspended),
-        this_object_(nullptr),
-        method_(nullptr),
-        dex_pc_(0),
-        abort_on_error_(abort_on_error) {}
-  bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) {
-    ArtMethod* m = GetMethod();
-    if (m->IsRuntimeMethod()) {
-      // Continue if this is a runtime method.
-      return true;
-    }
-    if (context_ != nullptr) {
-      this_object_ = GetThisObject();
-    }
-    method_ = m;
-    dex_pc_ = GetDexPc(abort_on_error_);
-    return false;
-  }
-  ObjPtr<mirror::Object> this_object_;
-  ArtMethod* method_;
-  uint32_t dex_pc_;
-  const bool abort_on_error_;
-};
-
 ArtMethod* Thread::GetCurrentMethod(uint32_t* dex_pc,
                                     bool check_suspended,
                                     bool abort_on_error) const {
-  CurrentMethodVisitor visitor(const_cast<Thread*>(this),
-                               nullptr,
-                               check_suspended,
-                               abort_on_error);
+  // Note: this visitor may return with a method set, but dex_pc_ being DexFile:kDexNoIndex. This is
+  //       so we don't abort in a special situation (thinlocked monitor) when dumping the Java
+  //       stack.
+  struct CurrentMethodVisitor final : public StackVisitor {
+    CurrentMethodVisitor(Thread* thread, bool check_suspended, bool abort_on_error)
+        REQUIRES_SHARED(Locks::mutator_lock_)
+        : StackVisitor(thread,
+                       /* context= */nullptr,
+            StackVisitor::StackWalkKind::kIncludeInlinedFrames,
+            check_suspended),
+            method_(nullptr),
+            dex_pc_(0),
+            abort_on_error_(abort_on_error) {}
+    bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) {
+      ArtMethod* m = GetMethod();
+      if (m->IsRuntimeMethod()) {
+        // Continue if this is a runtime method.
+        return true;
+      }
+      method_ = m;
+      dex_pc_ = GetDexPc(abort_on_error_);
+      return false;
+    }
+    ArtMethod* method_;
+    uint32_t dex_pc_;
+    const bool abort_on_error_;
+  };
+  CurrentMethodVisitor visitor(const_cast<Thread*>(this), check_suspended, abort_on_error);
   visitor.WalkStack(false);
   if (dex_pc != nullptr) {
     *dex_pc = visitor.dex_pc_;
diff --git a/test/530-checker-peel-unroll/smali/PeelUnroll.smali b/test/530-checker-peel-unroll/smali/PeelUnroll.smali
new file mode 100644
index 0000000..6e09e92
--- /dev/null
+++ b/test/530-checker-peel-unroll/smali/PeelUnroll.smali
@@ -0,0 +1,232 @@
+# Copyright (C) 2018 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.
+
+.class public LPeelUnroll;
+
+.super Ljava/lang/Object;
+
+## CHECK-START: void PeelUnroll.unrollingWhile(int[]) loop_optimization (before)
+## CHECK-DAG: <<Array:l\d+>>    ParameterValue                            loop:none
+## CHECK-DAG: <<Const0:i\d+>>   IntConstant 0                             loop:none
+## CHECK-DAG: <<Const1:i\d+>>   IntConstant 1                             loop:none
+## CHECK-DAG: <<Const2:i\d+>>   IntConstant 2                             loop:none
+## CHECK-DAG: <<Const128:i\d+>> IntConstant 128                           loop:none
+## CHECK-DAG: <<Limit:i\d+>>    IntConstant 4094                          loop:none
+## CHECK-DAG: <<PhiI:i\d+>>     Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
+## CHECK-DAG: <<PhiS:i\d+>>     Phi [<<Const128>>,{{i\d+}}]               loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<AddI:i\d+>>     Add [<<PhiI>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<Check:z\d+>>    GreaterThanOrEqual [<<PhiI>>,<<Limit>>]   loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<If:v\d+>>       If [<<Check>>]                            loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<Rem:i\d+>>      Rem [<<AddI>>,<<Const2>>]                 loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<NE:z\d+>>       NotEqual [<<Rem>>,<<Const0>>]             loop:<<Loop>>      outer_loop:none
+## CHECK-DAG:                   If [<<NE>>]                               loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<AddS:i\d+>>     Add [<<PhiS>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
+## CHECK-DAG:                   ArraySet                                  loop:<<Loop>>      outer_loop:none
+## CHECK-DAG:                   Phi [<<PhiS>>,<<AddS>>]                   loop:<<Loop>>      outer_loop:none
+
+## CHECK-NOT:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
+## CHECK-NOT:                   ArraySet                                  loop:<<Loop>>      outer_loop:none
+
+## CHECK-START: void PeelUnroll.unrollingWhile(int[]) loop_optimization (after)
+## CHECK-DAG: <<Array:l\d+>>    ParameterValue                            loop:none
+## CHECK-DAG: <<Const0:i\d+>>   IntConstant 0                             loop:none
+## CHECK-DAG: <<Const1:i\d+>>   IntConstant 1                             loop:none
+## CHECK-DAG: <<Const2:i\d+>>   IntConstant 2                             loop:none
+## CHECK-DAG: <<Const128:i\d+>> IntConstant 128                           loop:none
+## CHECK-DAG: <<Limit:i\d+>>    IntConstant 4094                          loop:none
+## CHECK-DAG: <<PhiI:i\d+>>     Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
+## CHECK-DAG: <<PhiS:i\d+>>     Phi [<<Const128>>,{{i\d+}}]               loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<AddI:i\d+>>     Add [<<PhiI>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<Check:z\d+>>    GreaterThanOrEqual [<<PhiI>>,<<Limit>>]   loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<If:v\d+>>       If [<<Check>>]                            loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<Rem:i\d+>>      Rem [<<AddI>>,<<Const2>>]                 loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<NE:z\d+>>       NotEqual [<<Rem>>,<<Const0>>]             loop:<<Loop>>      outer_loop:none
+## CHECK-DAG:                   If [<<NE>>]                               loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<AddS:i\d+>>     Add [<<PhiS>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
+## CHECK-DAG:                   ArraySet [{{l\d+}},{{i\d+}},<<PhiS>>]     loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<PhiSM:i\d+>>    Phi [<<PhiS>>,<<AddS>>]                   loop:<<Loop>>      outer_loop:none
+
+## CHECK-DAG: <<AddIA:i\d+>>    Add [<<AddI>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<CheckA:z\d+>>   GreaterThanOrEqual [<<AddI>>,<<Limit>>]   loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<IfA:v\d+>>      If [<<Const0>>]                           loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<RemA:i\d+>>     Rem [<<AddIA>>,<<Const2>>]                loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<NEA:z\d+>>      NotEqual [<<RemA>>,<<Const0>>]            loop:<<Loop>>      outer_loop:none
+## CHECK-DAG:                   If [<<NEA>>]                              loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<AddSA:i\d+>>    Add [<<PhiSM>>,<<Const1>>]                loop:<<Loop>>      outer_loop:none
+## CHECK-DAG:                   ArraySet [{{l\d+}},{{i\d+}},<<PhiSM>>]    loop:<<Loop>>      outer_loop:none
+## CHECK-DAG:                   Phi [<<AddSA>>,<<PhiSM>>]                 loop:<<Loop>>      outer_loop:none
+
+## CHECK-NOT:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
+## CHECK-NOT:                   ArraySet                                  loop:<<Loop>>      outer_loop:none
+.method public static final unrollingWhile([I)V
+    .registers 5
+    .param p0, "a"    # [I
+
+    .line 167
+    const/4 v0, 0x0
+
+    .line 168
+    .local v0, "i":I
+    const/16 v1, 0x80
+
+    .line 169
+    .local v1, "s":I
+    :goto_3
+    add-int/lit8 v2, v0, 0x1
+
+    .end local v0    # "i":I
+    .local v2, "i":I
+    const/16 v3, 0xffe
+
+    if-ge v0, v3, :cond_14
+
+    .line 170
+    rem-int/lit8 v0, v2, 0x2
+
+    if-nez v0, :cond_12
+
+    .line 171
+    add-int/lit8 v0, v1, 0x1
+
+    .end local v1    # "s":I
+    .local v0, "s":I
+    aput v1, p0, v2
+
+    .line 169
+    move v1, v0
+
+    .end local v2    # "i":I
+    .local v0, "i":I
+    .restart local v1    # "s":I
+    :cond_12
+    move v0, v2
+
+    goto :goto_3
+
+    .line 174
+    .end local v0    # "i":I
+    .restart local v2    # "i":I
+    :cond_14
+    return-void
+.end method
+
+
+## CHECK-START: int PeelUnroll.unrollingWhileLiveOuts(int[]) loop_optimization (before)
+## CHECK-DAG: <<Array:l\d+>>    ParameterValue                            loop:none
+## CHECK-DAG: <<Const0:i\d+>>   IntConstant 0                             loop:none
+## CHECK-DAG: <<Const1:i\d+>>   IntConstant 1                             loop:none
+## CHECK-DAG: <<Const2:i\d+>>   IntConstant 2                             loop:none
+## CHECK-DAG: <<Const128:i\d+>> IntConstant 128                           loop:none
+## CHECK-DAG: <<Limit:i\d+>>    IntConstant 4094                          loop:none
+## CHECK-DAG: <<PhiI:i\d+>>     Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
+## CHECK-DAG: <<PhiS:i\d+>>     Phi [<<Const128>>,{{i\d+}}]               loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<AddI:i\d+>>     Add [<<PhiI>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<Check:z\d+>>    GreaterThanOrEqual [<<PhiI>>,<<Limit>>]   loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<If:v\d+>>       If [<<Check>>]                            loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<Rem:i\d+>>      Rem [<<AddI>>,<<Const2>>]                 loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<NE:z\d+>>       NotEqual [<<Rem>>,<<Const0>>]             loop:<<Loop>>      outer_loop:none
+## CHECK-DAG:                   If [<<NE>>]                               loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<AddS:i\d+>>     Add [<<PhiS>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
+## CHECK-DAG:                   ArraySet                                  loop:<<Loop>>      outer_loop:none
+## CHECK-DAG:                   Phi [<<PhiS>>,<<AddS>>]                   loop:<<Loop>>      outer_loop:none
+
+## CHECK-NOT:                   ArrayGet
+## CHECK-NOT:                   ArraySet
+
+## CHECK-START: int PeelUnroll.unrollingWhileLiveOuts(int[]) loop_optimization (after)
+## CHECK-DAG: <<Array:l\d+>>    ParameterValue                            loop:none
+## CHECK-DAG: <<Const0:i\d+>>   IntConstant 0                             loop:none
+## CHECK-DAG: <<Const1:i\d+>>   IntConstant 1                             loop:none
+## CHECK-DAG: <<Const2:i\d+>>   IntConstant 2                             loop:none
+## CHECK-DAG: <<Const128:i\d+>> IntConstant 128                           loop:none
+## CHECK-DAG: <<Limit:i\d+>>    IntConstant 4094                          loop:none
+## CHECK-DAG: <<PhiI:i\d+>>     Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
+## CHECK-DAG: <<PhiS:i\d+>>     Phi [<<Const128>>,{{i\d+}}]               loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<AddI:i\d+>>     Add [<<PhiI>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<Check:z\d+>>    GreaterThanOrEqual [<<PhiI>>,<<Limit>>]   loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<If:v\d+>>       If [<<Check>>]                            loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<Rem:i\d+>>      Rem [<<AddI>>,<<Const2>>]                 loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<NE:z\d+>>       NotEqual [<<Rem>>,<<Const0>>]             loop:<<Loop>>      outer_loop:none
+## CHECK-DAG:                   If [<<NE>>]                               loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<AddS:i\d+>>     Add [<<PhiS>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
+## CHECK-DAG:                   ArraySet [{{l\d+}},{{i\d+}},<<PhiS>>]     loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<PhiSM:i\d+>>    Phi [<<PhiS>>,<<AddS>>]                   loop:<<Loop>>      outer_loop:none
+
+## CHECK-DAG: <<AddIA:i\d+>>    Add [<<AddI>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<CheckA:z\d+>>   GreaterThanOrEqual [<<AddI>>,<<Limit>>]   loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<IfA:v\d+>>      If [<<Const0>>]                           loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<RemA:i\d+>>     Rem [<<AddIA>>,<<Const2>>]                loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<NEA:z\d+>>      NotEqual [<<RemA>>,<<Const0>>]            loop:<<Loop>>      outer_loop:none
+## CHECK-DAG:                   If [<<NEA>>]                              loop:<<Loop>>      outer_loop:none
+## CHECK-DAG: <<AddSA:i\d+>>    Add [<<PhiSM>>,<<Const1>>]                loop:<<Loop>>      outer_loop:none
+## CHECK-DAG:                   ArraySet [{{l\d+}},{{i\d+}},<<PhiSM>>]    loop:<<Loop>>      outer_loop:none
+## CHECK-DAG:                   Phi [<<AddSA>>,<<PhiSM>>]                 loop:<<Loop>>      outer_loop:none
+
+## CHECK-DAG: <<RetPhi:i\d+>>   Phi [<<PhiS>>,<<PhiSM>>]                  loop:none
+## CHECK-DAG:                   Return [<<RetPhi>>]                       loop:none
+
+## CHECK-NOT:                   ArrayGet
+## CHECK-NOT:                   ArraySet
+.method public static final unrollingWhileLiveOuts([I)I
+    .registers 5
+    .param p0, "a"    # [I
+
+    .line 598
+    const/4 v0, 0x0
+
+    .line 599
+    .local v0, "i":I
+    const/16 v1, 0x80
+
+    .line 600
+    .local v1, "s":I
+    :goto_3
+    add-int/lit8 v2, v0, 0x1
+
+    .end local v0    # "i":I
+    .local v2, "i":I
+    const/16 v3, 0xffe
+
+    if-ge v0, v3, :cond_14
+
+    .line 601
+    rem-int/lit8 v0, v2, 0x2
+
+    if-nez v0, :cond_12
+
+    .line 602
+    add-int/lit8 v0, v1, 0x1
+
+    .end local v1    # "s":I
+    .local v0, "s":I
+    aput v1, p0, v2
+
+    .line 600
+    move v1, v0
+
+    .end local v2    # "i":I
+    .local v0, "i":I
+    .restart local v1    # "s":I
+    :cond_12
+    move v0, v2
+
+    goto :goto_3
+
+    .line 605
+    .end local v0    # "i":I
+    .restart local v2    # "i":I
+    :cond_14
+    return v1
+.end method
+
diff --git a/test/530-checker-peel-unroll/src/Main.java b/test/530-checker-peel-unroll/src/Main.java
index 4d81440..aee32b7 100644
--- a/test/530-checker-peel-unroll/src/Main.java
+++ b/test/530-checker-peel-unroll/src/Main.java
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+import java.lang.reflect.Method;
+
 //
 // Test loop optimizations, in particular scalar loop peeling and unrolling.
 public class Main {
@@ -110,69 +112,6 @@
     }
   }
 
-  /// CHECK-START: void Main.unrollingWhile(int[]) loop_optimization (before)
-  /// CHECK-DAG: <<Array:l\d+>>    ParameterValue                            loop:none
-  /// CHECK-DAG: <<Const0:i\d+>>   IntConstant 0                             loop:none
-  /// CHECK-DAG: <<Const1:i\d+>>   IntConstant 1                             loop:none
-  /// CHECK-DAG: <<Const2:i\d+>>   IntConstant 2                             loop:none
-  /// CHECK-DAG: <<Const128:i\d+>> IntConstant 128                           loop:none
-  /// CHECK-DAG: <<Limit:i\d+>>    IntConstant 4094                          loop:none
-  /// CHECK-DAG: <<PhiI:i\d+>>     Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<PhiS:i\d+>>     Phi [<<Const128>>,{{i\d+}}]               loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<AddI:i\d+>>     Add [<<PhiI>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Check:z\d+>>    GreaterThanOrEqual [<<PhiI>>,<<Limit>>]   loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<If:v\d+>>       If [<<Check>>]                            loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Rem:i\d+>>      Rem [<<AddI>>,<<Const2>>]                 loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<NE:z\d+>>       NotEqual [<<Rem>>,<<Const0>>]             loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                   If [<<NE>>]                               loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<AddS:i\d+>>     Add [<<PhiS>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                   ArraySet                                  loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                   Phi [<<PhiS>>,<<AddS>>]                   loop:<<Loop>>      outer_loop:none
-  //
-  /// CHECK-NOT:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
-  /// CHECK-NOT:                   ArraySet                                  loop:<<Loop>>      outer_loop:none
-
-  /// CHECK-START: void Main.unrollingWhile(int[]) loop_optimization (after)
-  /// CHECK-DAG: <<Array:l\d+>>    ParameterValue                            loop:none
-  /// CHECK-DAG: <<Const0:i\d+>>   IntConstant 0                             loop:none
-  /// CHECK-DAG: <<Const1:i\d+>>   IntConstant 1                             loop:none
-  /// CHECK-DAG: <<Const2:i\d+>>   IntConstant 2                             loop:none
-  /// CHECK-DAG: <<Const128:i\d+>> IntConstant 128                           loop:none
-  /// CHECK-DAG: <<Limit:i\d+>>    IntConstant 4094                          loop:none
-  /// CHECK-DAG: <<PhiI:i\d+>>     Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<PhiS:i\d+>>     Phi [<<Const128>>,{{i\d+}}]               loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<AddI:i\d+>>     Add [<<PhiI>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Check:z\d+>>    GreaterThanOrEqual [<<PhiI>>,<<Limit>>]   loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<If:v\d+>>       If [<<Check>>]                            loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Rem:i\d+>>      Rem [<<AddI>>,<<Const2>>]                 loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<NE:z\d+>>       NotEqual [<<Rem>>,<<Const0>>]             loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                   If [<<NE>>]                               loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<AddS:i\d+>>     Add [<<PhiS>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                   ArraySet [{{l\d+}},{{i\d+}},<<PhiS>>]     loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<PhiSM:i\d+>>    Phi [<<PhiS>>,<<AddS>>]                   loop:<<Loop>>      outer_loop:none
-  //
-  /// CHECK-DAG: <<AddIA:i\d+>>    Add [<<AddI>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<CheckA:z\d+>>   GreaterThanOrEqual [<<AddI>>,<<Limit>>]   loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<IfA:v\d+>>      If [<<Const0>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<RemA:i\d+>>     Rem [<<AddIA>>,<<Const2>>]                loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<NEA:z\d+>>      NotEqual [<<RemA>>,<<Const0>>]            loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                   If [<<NEA>>]                              loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<AddSA:i\d+>>    Add [<<PhiSM>>,<<Const1>>]                loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                   ArraySet [{{l\d+}},{{i\d+}},<<PhiSM>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                   Phi [<<AddSA>>,<<PhiSM>>]                 loop:<<Loop>>      outer_loop:none
-  //
-  /// CHECK-NOT:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
-  /// CHECK-NOT:                   ArraySet                                  loop:<<Loop>>      outer_loop:none
-  private static final void unrollingWhile(int[] a) {
-    int i = 0;
-    int s = 128;
-    while (i++ < LENGTH - 2) {
-      if (i % 2 == 0) {
-        a[i] = s++;
-      }
-    }
-  }
-
   // Simple check that loop unrolling has happened.
   //
   /// CHECK-START: void Main.unrollingSwitch(int[]) loop_optimization (before)
@@ -538,73 +477,6 @@
     return 1 / (s + t);
   }
 
-  /// CHECK-START: int Main.unrollingWhileLiveOuts(int[]) loop_optimization (before)
-  /// CHECK-DAG: <<Array:l\d+>>    ParameterValue                            loop:none
-  /// CHECK-DAG: <<Const0:i\d+>>   IntConstant 0                             loop:none
-  /// CHECK-DAG: <<Const1:i\d+>>   IntConstant 1                             loop:none
-  /// CHECK-DAG: <<Const2:i\d+>>   IntConstant 2                             loop:none
-  /// CHECK-DAG: <<Const128:i\d+>> IntConstant 128                           loop:none
-  /// CHECK-DAG: <<Limit:i\d+>>    IntConstant 4094                          loop:none
-  /// CHECK-DAG: <<PhiI:i\d+>>     Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<PhiS:i\d+>>     Phi [<<Const128>>,{{i\d+}}]               loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<AddI:i\d+>>     Add [<<PhiI>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Check:z\d+>>    GreaterThanOrEqual [<<PhiI>>,<<Limit>>]   loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<If:v\d+>>       If [<<Check>>]                            loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Rem:i\d+>>      Rem [<<AddI>>,<<Const2>>]                 loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<NE:z\d+>>       NotEqual [<<Rem>>,<<Const0>>]             loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                   If [<<NE>>]                               loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<AddS:i\d+>>     Add [<<PhiS>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                   ArraySet                                  loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                   Phi [<<PhiS>>,<<AddS>>]                   loop:<<Loop>>      outer_loop:none
-  //
-  /// CHECK-NOT:                   ArrayGet
-  /// CHECK-NOT:                   ArraySet
-
-  /// CHECK-START: int Main.unrollingWhileLiveOuts(int[]) loop_optimization (after)
-  /// CHECK-DAG: <<Array:l\d+>>    ParameterValue                            loop:none
-  /// CHECK-DAG: <<Const0:i\d+>>   IntConstant 0                             loop:none
-  /// CHECK-DAG: <<Const1:i\d+>>   IntConstant 1                             loop:none
-  /// CHECK-DAG: <<Const2:i\d+>>   IntConstant 2                             loop:none
-  /// CHECK-DAG: <<Const128:i\d+>> IntConstant 128                           loop:none
-  /// CHECK-DAG: <<Limit:i\d+>>    IntConstant 4094                          loop:none
-  /// CHECK-DAG: <<PhiI:i\d+>>     Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<PhiS:i\d+>>     Phi [<<Const128>>,{{i\d+}}]               loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<AddI:i\d+>>     Add [<<PhiI>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Check:z\d+>>    GreaterThanOrEqual [<<PhiI>>,<<Limit>>]   loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<If:v\d+>>       If [<<Check>>]                            loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Rem:i\d+>>      Rem [<<AddI>>,<<Const2>>]                 loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<NE:z\d+>>       NotEqual [<<Rem>>,<<Const0>>]             loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                   If [<<NE>>]                               loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<AddS:i\d+>>     Add [<<PhiS>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                   ArraySet [{{l\d+}},{{i\d+}},<<PhiS>>]     loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<PhiSM:i\d+>>    Phi [<<PhiS>>,<<AddS>>]                   loop:<<Loop>>      outer_loop:none
-  //
-  /// CHECK-DAG: <<AddIA:i\d+>>    Add [<<AddI>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<CheckA:z\d+>>   GreaterThanOrEqual [<<AddI>>,<<Limit>>]   loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<IfA:v\d+>>      If [<<Const0>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<RemA:i\d+>>     Rem [<<AddIA>>,<<Const2>>]                loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<NEA:z\d+>>      NotEqual [<<RemA>>,<<Const0>>]            loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                   If [<<NEA>>]                              loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<AddSA:i\d+>>    Add [<<PhiSM>>,<<Const1>>]                loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                   ArraySet [{{l\d+}},{{i\d+}},<<PhiSM>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                   Phi [<<AddSA>>,<<PhiSM>>]                 loop:<<Loop>>      outer_loop:none
-  //
-  /// CHECK-DAG: <<RetPhi:i\d+>>   Phi [<<PhiS>>,<<PhiSM>>]                  loop:none
-  /// CHECK-DAG:                   Return [<<RetPhi>>]                       loop:none
-  //
-  /// CHECK-NOT:                   ArrayGet
-  /// CHECK-NOT:                   ArraySet
-  private static final int unrollingWhileLiveOuts(int[] a) {
-    int i = 0;
-    int s = 128;
-    while (i++ < LENGTH - 2) {
-      if (i % 2 == 0) {
-        a[i] = s++;
-      }
-    }
-    return s;
-  }
-
   /// CHECK-START: int Main.unrollingLiveOutsNested(int[]) loop_optimization (before)
   /// CHECK-DAG: <<Array:l\d+>>   ParameterValue                            loop:none
   /// CHECK-DAG: <<Const0:i\d+>>  IntConstant 0                             loop:none
@@ -1113,7 +985,7 @@
     }
   }
 
-  public void verifyUnrolling() {
+  public void verifyUnrolling() throws Exception {
     initIntArray(a);
     initIntArray(b);
 
@@ -1132,7 +1004,12 @@
     unrollingTypeConversion(a, doubleArray);
     unrollingCheckCast(a, new SubMain());
 
-    unrollingWhile(a);
+    // Call unrollingWhile(a);
+    Class<?> c = Class.forName("PeelUnroll");
+    Method m = c.getMethod("unrollingWhile", Class.forName("[I"));
+    Object[] arguments = { a };
+    m.invoke(null, arguments);
+
     unrollingLoadStoreElimination(a);
     unrollingSwitch(a);
     unrollingSwapElements(a);
@@ -1152,7 +1029,7 @@
     expectEquals(expected, found);
   }
 
-  public void verifyPeeling() {
+  public void verifyPeeling() throws Exception {
     expectEquals(1, peelingHoistOneControl(0));  // anything else loops
     expectEquals(1, peelingHoistOneControl(0, 0));
     expectEquals(1, peelingHoistOneControl(0, 1));
@@ -1176,7 +1053,13 @@
     peelingBreakFromNest(a, true);
 
     unrollingSimpleLiveOuts(a);
-    unrollingWhileLiveOuts(a);
+
+    // Call unrollingWhileLiveOuts(a);
+    Class<?> c = Class.forName("PeelUnroll");
+    Method m = c.getMethod("unrollingWhileLiveOuts", Class.forName("[I"));
+    Object[] arguments = { a };
+    m.invoke(null, arguments);
+
     unrollingLiveOutsNested(a);
 
     int expected = 51565978;
@@ -1188,7 +1071,7 @@
     expectEquals(expected, found);
   }
 
-  public static void main(String[] args) {
+  public static void main(String[] args) throws Exception {
     Main obj = new Main();
 
     obj.verifyUnrolling();
diff --git a/test/knownfailures.json b/test/knownfailures.json
index a7fb189..002ad07 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -295,7 +295,7 @@
                   "685-deoptimizeable"],
         "description": ["Tests that should fail when the optimizing compiler ",
                         "compiles them non-debuggable."],
-        "variant": "optimizing & ndebuggable | regalloc_gc & ndebuggable | speed-profile & ndebuggable | jit & ndebuggable"
+        "variant": "optimizing & ndebuggable | regalloc_gc & ndebuggable | speed-profile & ndebuggable | jit & ndebuggable | jit-on-first-use & ndebuggable"
     },
     {
         "tests": "596-app-images",
@@ -702,7 +702,7 @@
     },
     {
         "tests": ["661-oat-writer-layout"],
-        "variant": "interp-ac | interpreter | jit | no-prebuild | no-image | trace | redefine-stress | jvmti-stress",
+        "variant": "interp-ac | interpreter | jit | jit-on-first-use | no-prebuild | no-image | trace | redefine-stress | jvmti-stress",
         "description": ["Test is designed to only check --optimizing"]
     },
     {
@@ -1017,7 +1017,8 @@
         "description": ["Failing on RI. Needs further investigating."]
     },
     {
-        "tests": ["616-cha-unloading",
+        "tests": ["530-checker-peel-unroll",
+                  "616-cha-unloading",
                   "674-hiddenapi",
                   "677-fsi2",
                   "678-quickening",
diff --git a/test/testrunner/run_build_test_target.py b/test/testrunner/run_build_test_target.py
index 3160079..14287b0 100755
--- a/test/testrunner/run_build_test_target.py
+++ b/test/testrunner/run_build_test_target.py
@@ -63,11 +63,12 @@
 os.environ.update(custom_env)
 
 if 'make' in target:
-  build_command = 'make'
+  build_command = 'build/soong/soong_ui.bash --make-mode'
   build_command += ' DX='
   build_command += ' -j' + str(n_threads)
-  build_command += ' -C ' + env.ANDROID_BUILD_TOP
   build_command += ' ' + target.get('make')
+  if env.DIST_DIR:
+    build_command += ' dist'
   sys.stdout.write(str(build_command) + '\n')
   sys.stdout.flush()
   if subprocess.call(build_command.split()):
diff --git a/test/testrunner/target_config.py b/test/testrunner/target_config.py
index ad72945..c532705 100644
--- a/test/testrunner/target_config.py
+++ b/test/testrunner/target_config.py
@@ -47,8 +47,7 @@
         'run-test' : ['--jit', '--debuggable', '--ndebuggable']
     },
     'art-jit-on-first-use' : {
-        'run-test' : ['--jit',
-                      '--runtime-option=-Xjitthreshold:0']
+        'run-test' : ['--jit-on-first-use']
     },
     'art-pictest' : {
         'run-test' : ['--pictest',
@@ -81,9 +80,8 @@
                       '--gcverify']
     },
     'art-jit-on-first-use-gcstress' : {
-        'run-test' : ['--jit',
-                      '--gcstress',
-                      '--runtime-option=-Xjitthreshold:0']
+        'run-test' : ['--jit-on-first-use',
+                      '--gcstress']
     },
     'art-read-barrier-heap-poisoning' : {
         'run-test': ['--interpreter',
diff --git a/test/testrunner/testrunner.py b/test/testrunner/testrunner.py
index 2fa7d2a..c5059f6 100755
--- a/test/testrunner/testrunner.py
+++ b/test/testrunner/testrunner.py
@@ -153,8 +153,8 @@
   VARIANT_TYPE_DICT['address_sizes'] = {'64', '32'}
   VARIANT_TYPE_DICT['jvmti'] = {'no-jvmti', 'jvmti-stress', 'redefine-stress', 'trace-stress',
                                 'field-stress', 'step-stress'}
-  VARIANT_TYPE_DICT['compiler'] = {'interp-ac', 'interpreter', 'jit', 'optimizing',
-                                   'regalloc_gc', 'speed-profile'}
+  VARIANT_TYPE_DICT['compiler'] = {'interp-ac', 'interpreter', 'jit', 'jit-on-first-use',
+                                   'optimizing', 'regalloc_gc', 'speed-profile'}
 
   for v_type in VARIANT_TYPE_DICT:
     TOTAL_VARIANTS_SET = TOTAL_VARIANTS_SET.union(VARIANT_TYPE_DICT.get(v_type))
@@ -433,6 +433,8 @@
         options_test += ' --interpreter --verify-soft-fail'
       elif compiler == 'jit':
         options_test += ' --jit'
+      elif compiler == 'jit-on-first-use':
+        options_test += ' --jit --runtime-option -Xjitthreshold:0'
       elif compiler == 'speed-profile':
         options_test += ' --random-profile'
 
@@ -1019,10 +1021,8 @@
       build_targets += 'test-art-target-run-test-dependencies '
     if 'jvm' in _user_input_variants['target']:
       build_targets += 'test-art-host-run-test-dependencies '
-    build_command = 'make'
+    build_command = 'build/soong/soong_ui.bash --make-mode'
     build_command += ' DX='
-    build_command += ' -j'
-    build_command += ' -C ' + env.ANDROID_BUILD_TOP
     build_command += ' ' + build_targets
     if subprocess.call(build_command.split()):
       # Debugging for b/62653020
diff --git a/test/ti-agent/jni_binder.cc b/test/ti-agent/jni_binder.cc
index 32236de..585b4a4 100644
--- a/test/ti-agent/jni_binder.cc
+++ b/test/ti-agent/jni_binder.cc
@@ -223,7 +223,7 @@
   }
 
   // TODO: Implement scanning *all* classloaders.
-  LOG(FATAL) << "Unimplemented";
+  LOG(WARNING) << "Scanning all classloaders unimplemented";
 
   return nullptr;
 }