Merge "Make VariableHandleScope consistent between 32 & 64 bit"
diff --git a/Android.mk b/Android.mk
index ba131c6..1a5daff 100644
--- a/Android.mk
+++ b/Android.mk
@@ -31,13 +31,8 @@
 .PHONY: clean-oat-host
 clean-oat-host:
 	find $(OUT_DIR) -name "*.oat" -o -name "*.odex" -o -name "*.art" -o -name '*.vdex' | xargs rm -f
-ifneq ($(TMPDIR),)
-	rm -rf $(TMPDIR)/$(USER)/test-*/dalvik-cache/*
+	rm -rf $(TMPDIR)/*/test-*/dalvik-cache/*
 	rm -rf $(TMPDIR)/android-data/dalvik-cache/*
-else
-	rm -rf /tmp/$(USER)/test-*/dalvik-cache/*
-	rm -rf /tmp/android-data/dalvik-cache/*
-endif
 
 .PHONY: clean-oat-target
 clean-oat-target:
@@ -68,7 +63,6 @@
 include $(art_path)/tools/amm/Android.mk
 include $(art_path)/tools/dexfuzz/Android.mk
 include $(art_path)/tools/veridex/Android.mk
-include $(art_path)/libart_fake/Android.mk
 
 ART_HOST_DEPENDENCIES := \
   $(ART_HOST_EXECUTABLES) \
@@ -393,9 +387,6 @@
     profman \
     libadbconnection \
 
-# For nosy apps, we provide a fake library that avoids namespace issues and gives some warnings.
-LOCAL_REQUIRED_MODULES += libart_fake
-
 # Potentially add in debug variants:
 #
 # * We will never add them if PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD = false.
@@ -497,6 +488,22 @@
 .PHONY: build-art-target-golem
 # Also include libartbenchmark, we always include it when running golem.
 # libstdc++ is needed when building for ART_TARGET_LINUX.
+#
+# Also include the bootstrap Bionic libraries (libc, libdl, libm).
+# These are required as the "main" libc, libdl, and libm have moved to
+# the Runtime APEX. This is a temporary change needed until Golem
+# fully supports the Runtime APEX.
+# TODO(b/121117762): Remove this when the ART Buildbot and Golem have
+# full support for the Runtime APEX.
+#
+# Also include a copy of the ICU .dat prebuilt files in
+# /system/etc/icu on target (see module `icu-data-art-test`), so that
+# it can found even if the Runtime APEX is not available, by setting
+# the environment variable `ART_TEST_ANDROID_RUNTIME_ROOT` to
+# "/system" on device. This is a temporary change needed until Golem
+# fully supports the Runtime APEX.
+# TODO(b/121117762): Remove this when the ART Buildbot and Golem have
+# full support for the Runtime APEX.
 ART_TARGET_SHARED_LIBRARY_BENCHMARK := $(TARGET_OUT_SHARED_LIBRARIES)/libartbenchmark.so
 build-art-target-golem: dex2oat dalvikvm linker libstdc++ \
                         $(TARGET_OUT_EXECUTABLES)/art \
@@ -505,7 +512,9 @@
                         $(ART_TARGET_SHARED_LIBRARY_DEPENDENCIES) \
                         $(ART_TARGET_SHARED_LIBRARY_BENCHMARK) \
                         $(TARGET_CORE_IMG_OUT_BASE).art \
-                        $(TARGET_CORE_IMG_OUT_BASE)-interpreter.art
+                        $(TARGET_CORE_IMG_OUT_BASE)-interpreter.art \
+                        libc.bootstrap libdl.bootstrap libm.bootstrap \
+                        icu-data-art-test
 	# remove debug libraries from public.libraries.txt because golem builds
 	# won't have it.
 	sed -i '/libartd.so/d' $(TARGET_OUT)/etc/public.libraries.txt
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 341df78..e28ce2b 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -1,4 +1,4 @@
-# Copyright (C) 2007 The Android Open Source Project
+# Copyright (C) 2014 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.
@@ -50,6 +50,9 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libart_*)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libartd_*)
 
+# Old Android Runtime APEX package, before the introduction of "release" and "debug" packages.
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/apex/com.android.runtime.apex)
+
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/build/Android.common_path.mk b/build/Android.common_path.mk
index c73b988..5208d64 100644
--- a/build/Android.common_path.mk
+++ b/build/Android.common_path.mk
@@ -74,8 +74,7 @@
 TARGET_CORE_IMG_LOCATION := $(ART_TARGET_TEST_OUT)/core.art
 
 # Modules to compile for core.art.
-# TODO: Move conscrypt from CORE_IMG_JARS to TEST_CORE_JARS and adjust scripts to fix Golem.
-CORE_IMG_JARS := core-oj core-libart core-simple okhttp bouncycastle apache-xml conscrypt
+CORE_IMG_JARS := core-oj core-libart core-simple okhttp bouncycastle apache-xml
 HOST_CORE_IMG_JARS   := $(addsuffix -hostdex,$(CORE_IMG_JARS))
 TARGET_CORE_IMG_JARS := $(addsuffix -testdex,$(CORE_IMG_JARS))
 HOST_CORE_IMG_DEX_LOCATIONS   := $(foreach jar,$(HOST_CORE_IMG_JARS),  $(HOST_OUT_JAVA_LIBRARIES)/$(jar).jar)
@@ -88,7 +87,7 @@
 TARGET_CORE_IMG_DEX_FILES := $(foreach jar,$(TARGET_CORE_IMG_JARS),$(call intermediates-dir-for,JAVA_LIBRARIES,$(jar), ,COMMON)/javalib.jar)
 
 # Jar files for the boot class path for testing. Must start with CORE_IMG_JARS.
-TEST_CORE_JARS := $(CORE_IMG_JARS)
+TEST_CORE_JARS := $(CORE_IMG_JARS) conscrypt
 HOST_TEST_CORE_JARS   := $(addsuffix -hostdex,$(TEST_CORE_JARS))
 TARGET_TEST_CORE_JARS := $(addsuffix -testdex,$(TEST_CORE_JARS))
 HOST_CORE_DEX_LOCATIONS   := $(foreach jar,$(HOST_TEST_CORE_JARS),  $(HOST_OUT_JAVA_LIBRARIES)/$(jar).jar)
diff --git a/build/Android.common_test.mk b/build/Android.common_test.mk
index be1791b..12eae89 100644
--- a/build/Android.common_test.mk
+++ b/build/Android.common_test.mk
@@ -20,12 +20,8 @@
 include art/build/Android.common_path.mk
 
 # Directory used for temporary test files on the host.
-# Use a hash calculated from CWD and USER as one of the path
-# components for the test output. This should allow us to run tests from
-# multiple repositories at the same time.
-# We only take the first few characters to keep paths short.
-ART_TMPDIR := $(if $(TMPDIR),$(TMPDIR),/tmp)
-ART_HOST_TEST_DIR := $(ART_TMPDIR)/test-art-$(shell echo $$CWD-${USER} | $(MD5SUM) | cut -c-5)
+# TMPDIR is always provided by the build system as $OUT_DIR-unique temporary directory.
+ART_HOST_TEST_DIR := $(TMPDIR)/test-art
 
 # List of known broken tests that we won't attempt to execute. The test name must be the full
 # rule name such as test-art-host-oat-optimizing-HelloWorld64.
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index a926d9a..f00da9c 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -371,8 +371,8 @@
 
 ART_TEST_MODULES := \
     art_cmdline_tests \
-    art_compiler_tests \
     art_compiler_host_tests \
+    art_compiler_tests \
     art_dex2oat_tests \
     art_dexanalyze_tests \
     art_dexdiag_tests \
@@ -383,12 +383,14 @@
     art_hiddenapi_tests \
     art_imgdiag_tests \
     art_libartbase_tests \
+    art_libdexfile_external_tests \
+    art_libdexfile_support_tests \
     art_libdexfile_tests \
     art_libprofile_tests \
     art_oatdump_tests \
     art_profman_tests \
-    art_runtime_tests \
     art_runtime_compiler_tests \
+    art_runtime_tests \
     art_sigchain_tests \
 
 ART_TARGET_GTEST_FILES := $(foreach m,$(ART_TEST_MODULES),\
@@ -423,6 +425,9 @@
 endif
 
 ART_GTEST_TARGET_ANDROID_RUNTIME_ROOT := '/apex/com.android.runtime'
+ifneq ($(ART_TEST_ANDROID_RUNTIME_ROOT),)
+  ART_GTEST_TARGET_ANDROID_RUNTIME_ROOT := $(ART_TEST_ANDROID_RUNTIME_ROOT)
+endif
 
 # Define a make rule for a target device gtest.
 # $(1): gtest name - the name of the test we're building such as leb128_test.
diff --git a/build/apex/Android.bp b/build/apex/Android.bp
index 193a3c1..47729c1 100644
--- a/build/apex/Android.bp
+++ b/build/apex/Android.bp
@@ -28,21 +28,7 @@
 bionic_binaries_both = [
     "linker",
 ]
-// - Fake library that avoids namespace issues and gives some warnings for nosy apps.
-art_runtime_fake_native_shared_libs = [
-     // FIXME: Does not work as-is, because `libart_fake` is defined in libart_fake/Android.mk,
-     // and because a module defined in a Blueprint file cannot depend on a module defined in a
-     // Makefile. To support `libart_fake` as a dependency of this APEX module, we can either
-     // (probably in that order of preference):
-     // a. translate that logic into Blueprint; or
-     // b. write the whole Android Runtime APEX generation logic in Android.mk; or
-     // c. introduce an `art_apex` module type extending the `apex` module type and write the
-     //    corresponding Go logic to handle this extra dependency.
-     //"libart_fake",
-]
 // - Debug variants (binaries for which a 32-bit version is preferred).
-//   FIXME: These modules are optional (the built product can decide to include them or not).
-//   Should they be moved to another APEX file?
 art_runtime_debug_binaries_prefer32 = [
     "dex2oatd",
     "dexoptanalyzerd",
@@ -55,14 +41,14 @@
     "libopenjdkjvmd",
     "libopenjdkjvmtid",
     "libadbconnectiond",
-    "libjavacrypto",
 ]
 
-// Files associated with bionic / managed core library time zone APIs.
-art_runtime_time_zone_prebuilts = [
+// Data files associated with bionic / managed core library APIs.
+art_runtime_data_file_prebuilts = [
     "apex_tz_version",
     "apex_tzdata",
     "apex_tzlookup.xml",
+    "apex_icu.dat",
 ]
 
 // Modules listed in LOCAL_REQUIRED_MODULES for module art-tools in art/Android.mk.
@@ -72,13 +58,15 @@
     "dexlist",
 ]
 
-art_tools_device_binaries = [
+// Device-only modules listed in LOCAL_REQUIRED_MODULES for module art-tools in art/Android.mk.
+art_tools_device_only_binaries = [
+    // oatdump cannot link with host linux_bionic due to not using clang lld;
+    // TODO: Make it work with clang lld.
     "oatdump",
 ]
 
 // Host-only modules listed in LOCAL_REQUIRED_MODULES for module art-tools in art/Android.mk.
-// TODO: Include these modules in the future "host APEX".
-art_tools_host_binaries = [
+art_tools_host_only_binaries = [
     // FIXME: Does not work as-is, because `ahat` is defined in tools/ahat/Android.mk
     // (same issue as for `libart_fake` above).
     //"ahat",
@@ -86,7 +74,8 @@
     // ...
 ]
 
-art_tools_binaries = art_tools_common_binaries + art_tools_device_binaries
+art_tools_device_binaries = art_tools_common_binaries + art_tools_device_only_binaries
+art_tools_host_binaries = art_tools_common_binaries + art_tools_host_only_binaries
 
 apex_key {
     name: "com.android.runtime.key",
@@ -112,7 +101,6 @@
     compile_multilib: "both",
     manifest: "manifest.json",
     native_shared_libs: art_runtime_base_native_shared_libs
-        + art_runtime_fake_native_shared_libs
         + bionic_native_shared_libs,
     multilib: {
         both: {
@@ -128,7 +116,7 @@
             binaries: [],
         }
     },
-    prebuilts: art_runtime_time_zone_prebuilts
+    prebuilts: art_runtime_data_file_prebuilts
         + ["com.android.runtime.ld.config.txt"],
     key: "com.android.runtime.key",
 }
@@ -141,7 +129,6 @@
     compile_multilib: "both",
     manifest: "manifest.json",
     native_shared_libs: art_runtime_base_native_shared_libs
-        + art_runtime_fake_native_shared_libs
         + art_runtime_debug_native_shared_libs
         + bionic_native_shared_libs,
     multilib: {
@@ -156,10 +143,10 @@
                 + art_runtime_debug_binaries_prefer32,
         },
         first: {
-            binaries: art_tools_binaries,
+            binaries: art_tools_device_binaries,
         }
     },
-    prebuilts: art_runtime_time_zone_prebuilts
+    prebuilts: art_runtime_data_file_prebuilts
         + ["com.android.runtime.ld.config.txt"],
     key: "com.android.runtime.key",
 }
@@ -177,7 +164,6 @@
     device_supported: false,
     manifest: "manifest.json",
     native_shared_libs: art_runtime_base_native_shared_libs
-        + art_runtime_fake_native_shared_libs
         + art_runtime_debug_native_shared_libs,
     multilib: {
         both: {
@@ -186,8 +172,7 @@
             binaries: art_runtime_base_binaries_both,
         },
         first: {
-            // TODO: oatdump cannot link with host linux_bionic due to not using clang ld
-            binaries: art_tools_common_binaries
+            binaries: art_tools_host_binaries
                 + art_runtime_base_binaries_prefer32
                 + art_runtime_debug_binaries_prefer32,
         }
diff --git a/build/apex/ld.config.txt b/build/apex/ld.config.txt
index 014b115..9e49d76 100644
--- a/build/apex/ld.config.txt
+++ b/build/apex/ld.config.txt
@@ -24,8 +24,7 @@
 namespace.platform.isolated = true
 namespace.platform.search.paths = /system/${LIB}
 namespace.platform.links = default
-namespace.platform.link.default.shared_libs  = libc.so:libdl.so:libm.so
-namespace.platform.link.default.shared_libs += libart.so:libartd.so
+namespace.platform.link.default.shared_libs  = libart.so:libartd.so
 namespace.platform.link.default.shared_libs += libnativebridge.so
 namespace.platform.link.default.shared_libs += libnativehelper.so
 namespace.platform.link.default.shared_libs += libnativeloader.so
diff --git a/build/apex/runtests.sh b/build/apex/runtests.sh
index b5e8d8b..9db325a 100755
--- a/build/apex/runtests.sh
+++ b/build/apex/runtests.sh
@@ -146,18 +146,19 @@
   # TODO: Check for it when it is also built for host.
   : check_binary oatdump
 
-  # Check that the mounted image contains ART libraries.
+  # Check that the mounted image contains Android Runtime libraries.
   check_library libart-compiler.so
+  check_library libart-dexlayout.so
   check_library libart.so
+  check_library libartbase.so
+  check_library libdexfile.so
   check_library libopenjdkjvm.so
   check_library libopenjdkjvmti.so
-  check_library libadbconnection.so
-  # TODO: Should we check for these libraries too, even if they are not explicitly
-  # listed as dependencies in the Android Runtime APEX module rule?
-  check_library libartbase.so
-  check_library libart-dexlayout.so
-  check_library libdexfile.so
   check_library libprofile.so
+  # Check that the mounted image contains Android Core libraries.
+  check_library libjavacrypto.so
+  # Check that the mounted image contains additional required libraries.
+  check_library libadbconnection.so
 
   # TODO: Should we check for other libraries, such as:
   #
@@ -186,19 +187,18 @@
   check_binary dexoptanalyzerd
   check_binary profmand
 
-  # Check that the mounted image contains ART debug libraries.
+  # Check that the mounted image contains Android Runtime debug libraries.
+  check_library libartbased.so
   check_library libartd-compiler.so
+  check_library libartd-dexlayout.so
   check_library libartd.so
+  check_library libdexfiled.so
   check_library libopenjdkd.so
   check_library libopenjdkjvmd.so
   check_library libopenjdkjvmtid.so
-  check_library libadbconnectiond.so
-  # TODO: Should we check for these libraries too, even if they are not explicitly
-  # listed as dependencies in the Android Runtime APEX module rule?
-  check_library libdexfiled.so
-  check_library libartbased.so
-  check_library libartd-dexlayout.so
   check_library libprofiled.so
+  # Check that the mounted image contains additional required libraries.
+  check_library libadbconnectiond.so
 }
 
 # Testing target (device) APEX packages.
diff --git a/compiler/jni/quick/arm/calling_convention_arm.cc b/compiler/jni/quick/arm/calling_convention_arm.cc
index 8b4bab7..42a4603 100644
--- a/compiler/jni/quick/arm/calling_convention_arm.cc
+++ b/compiler/jni/quick/arm/calling_convention_arm.cc
@@ -18,6 +18,7 @@
 
 #include <android-base/logging.h>
 
+#include "arch/instruction_set.h"
 #include "base/macros.h"
 #include "handle_scope-inl.h"
 #include "utils/arm/managed_register_arm.h"
diff --git a/compiler/jni/quick/arm64/calling_convention_arm64.cc b/compiler/jni/quick/arm64/calling_convention_arm64.cc
index 4e6221e..4a6a754 100644
--- a/compiler/jni/quick/arm64/calling_convention_arm64.cc
+++ b/compiler/jni/quick/arm64/calling_convention_arm64.cc
@@ -18,6 +18,7 @@
 
 #include <android-base/logging.h>
 
+#include "arch/instruction_set.h"
 #include "handle_scope-inl.h"
 #include "utils/arm64/managed_register_arm64.h"
 
diff --git a/compiler/jni/quick/calling_convention.cc b/compiler/jni/quick/calling_convention.cc
index ff814c8..f031b9b 100644
--- a/compiler/jni/quick/calling_convention.cc
+++ b/compiler/jni/quick/calling_convention.cc
@@ -18,6 +18,8 @@
 
 #include <android-base/logging.h>
 
+#include "arch/instruction_set.h"
+
 #ifdef ART_ENABLE_CODEGEN_arm
 #include "jni/quick/arm/calling_convention_arm.h"
 #endif
diff --git a/compiler/jni/quick/calling_convention.h b/compiler/jni/quick/calling_convention.h
index e256ce6..77a5d59 100644
--- a/compiler/jni/quick/calling_convention.h
+++ b/compiler/jni/quick/calling_convention.h
@@ -27,6 +27,8 @@
 
 namespace art {
 
+enum class InstructionSet;
+
 // Top-level abstraction for different calling conventions.
 class CallingConvention : public DeletableArenaObject<kArenaAllocCallingConvention> {
  public:
diff --git a/compiler/jni/quick/mips/calling_convention_mips.cc b/compiler/jni/quick/mips/calling_convention_mips.cc
index d3d489e..c69854d 100644
--- a/compiler/jni/quick/mips/calling_convention_mips.cc
+++ b/compiler/jni/quick/mips/calling_convention_mips.cc
@@ -18,6 +18,7 @@
 
 #include <android-base/logging.h>
 
+#include "arch/instruction_set.h"
 #include "handle_scope-inl.h"
 #include "utils/mips/managed_register_mips.h"
 
diff --git a/compiler/jni/quick/mips64/calling_convention_mips64.cc b/compiler/jni/quick/mips64/calling_convention_mips64.cc
index 3c7cee6..2c297b3 100644
--- a/compiler/jni/quick/mips64/calling_convention_mips64.cc
+++ b/compiler/jni/quick/mips64/calling_convention_mips64.cc
@@ -18,6 +18,7 @@
 
 #include <android-base/logging.h>
 
+#include "arch/instruction_set.h"
 #include "handle_scope-inl.h"
 #include "utils/mips64/managed_register_mips64.h"
 
diff --git a/compiler/jni/quick/x86/calling_convention_x86.cc b/compiler/jni/quick/x86/calling_convention_x86.cc
index 71e6019..1f255e2 100644
--- a/compiler/jni/quick/x86/calling_convention_x86.cc
+++ b/compiler/jni/quick/x86/calling_convention_x86.cc
@@ -18,6 +18,7 @@
 
 #include <android-base/logging.h>
 
+#include "arch/instruction_set.h"
 #include "handle_scope-inl.h"
 #include "utils/x86/managed_register_x86.h"
 
diff --git a/compiler/jni/quick/x86_64/calling_convention_x86_64.cc b/compiler/jni/quick/x86_64/calling_convention_x86_64.cc
index e5e96d0..9e77d6b 100644
--- a/compiler/jni/quick/x86_64/calling_convention_x86_64.cc
+++ b/compiler/jni/quick/x86_64/calling_convention_x86_64.cc
@@ -18,6 +18,7 @@
 
 #include <android-base/logging.h>
 
+#include "arch/instruction_set.h"
 #include "base/bit_utils.h"
 #include "handle_scope-inl.h"
 #include "utils/x86_64/managed_register_x86_64.h"
diff --git a/compiler/optimizing/block_builder.cc b/compiler/optimizing/block_builder.cc
index 3672cce..a5f78ca 100644
--- a/compiler/optimizing/block_builder.cc
+++ b/compiler/optimizing/block_builder.cc
@@ -315,8 +315,16 @@
     CatchHandlerIterator iterator(handlers_ptr);
     for (; iterator.HasNext(); iterator.Next()) {
       uint32_t address = iterator.GetHandlerAddress();
-      if (catch_blocks.find(address) != catch_blocks.end()) {
+      auto existing = catch_blocks.find(address);
+      if (existing != catch_blocks.end()) {
         // Catch block already processed.
+        TryCatchInformation* info = existing->second->GetTryCatchInformation();
+        if (iterator.GetHandlerTypeIndex() != info->GetCatchTypeIndex()) {
+          // The handler is for multiple types. We could record all the types, but
+          // doing class resolution here isn't ideal, and it's unclear whether wasting
+          // the space in TryCatchInformation is worth it.
+          info->SetInvalidTypeIndex();
+        }
         continue;
       }
 
@@ -337,7 +345,7 @@
 
       catch_blocks.Put(address, catch_block);
       catch_block->SetTryCatchInformation(
-        new (allocator_) TryCatchInformation(iterator.GetHandlerTypeIndex(), *dex_file_));
+          new (allocator_) TryCatchInformation(iterator.GetHandlerTypeIndex(), *dex_file_));
     }
     handlers_ptr = iterator.EndDataPointer();
   }
diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc
index ae1650e..ca790f6 100644
--- a/compiler/optimizing/intrinsics_arm64.cc
+++ b/compiler/optimizing/intrinsics_arm64.cc
@@ -3086,10 +3086,10 @@
 void IntrinsicCodeGeneratorARM64::VisitCRC32UpdateBytes(HInvoke* invoke) {
   DCHECK(codegen_->GetInstructionSetFeatures().HasCRC());
 
-  auto masm = GetVIXLAssembler();
-  auto locations = invoke->GetLocations();
+  MacroAssembler* masm = GetVIXLAssembler();
+  LocationSummary* locations = invoke->GetLocations();
 
-  auto slow_path =
+  SlowPathCodeARM64* slow_path =
     new (codegen_->GetScopedAllocator()) IntrinsicSlowPathARM64(invoke);
   codegen_->AddSlowPath(slow_path);
 
@@ -3101,7 +3101,7 @@
       mirror::Array::DataOffset(Primitive::kPrimByte).Uint32Value();
   Register ptr = XRegisterFrom(locations->GetTemp(0));
   Register array = XRegisterFrom(locations->InAt(1));
-  auto offset = locations->InAt(2);
+  Location offset = locations->InAt(2);
   if (offset.IsConstant()) {
     int32_t offset_value = offset.GetConstant()->AsIntConstant()->GetValue();
     __ Add(ptr, array, array_data_offset + offset_value);
@@ -3148,8 +3148,8 @@
 void IntrinsicCodeGeneratorARM64::VisitCRC32UpdateByteBuffer(HInvoke* invoke) {
   DCHECK(codegen_->GetInstructionSetFeatures().HasCRC());
 
-  auto masm = GetVIXLAssembler();
-  auto locations = invoke->GetLocations();
+  MacroAssembler* masm = GetVIXLAssembler();
+  LocationSummary* locations = invoke->GetLocations();
 
   Register addr = XRegisterFrom(locations->InAt(1));
   Register ptr = XRegisterFrom(locations->GetTemp(0));
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 686a2de..48fb611 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -895,7 +895,7 @@
   explicit TryCatchInformation(const HTryBoundary& try_entry)
       : try_entry_(&try_entry),
         catch_dex_file_(nullptr),
-        catch_type_index_(DexFile::kDexNoIndex16) {
+        catch_type_index_(dex::TypeIndex::Invalid()) {
     DCHECK(try_entry_ != nullptr);
   }
 
@@ -914,9 +914,9 @@
 
   bool IsCatchBlock() const { return catch_dex_file_ != nullptr; }
 
-  bool IsCatchAllTypeIndex() const {
+  bool IsValidTypeIndex() const {
     DCHECK(IsCatchBlock());
-    return !catch_type_index_.IsValid();
+    return catch_type_index_.IsValid();
   }
 
   dex::TypeIndex GetCatchTypeIndex() const {
@@ -929,6 +929,10 @@
     return *catch_dex_file_;
   }
 
+  void SetInvalidTypeIndex() {
+    catch_type_index_ = dex::TypeIndex::Invalid();
+  }
+
  private:
   // One of possibly several TryBoundary instructions entering the block's try.
   // Only set for try blocks.
@@ -936,7 +940,7 @@
 
   // Exception type information. Only set for catch blocks.
   const DexFile* catch_dex_file_;
-  const dex::TypeIndex catch_type_index_;
+  dex::TypeIndex catch_type_index_;
 };
 
 static constexpr size_t kNoLifetime = -1;
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc
index 61e7a60..4929e0a 100644
--- a/compiler/optimizing/reference_type_propagation.cc
+++ b/compiler/optimizing/reference_type_propagation.cc
@@ -699,14 +699,14 @@
   DCHECK(instr->GetBlock()->IsCatchBlock());
   TryCatchInformation* catch_info = instr->GetBlock()->GetTryCatchInformation();
 
-  if (catch_info->IsCatchAllTypeIndex()) {
-    instr->SetReferenceTypeInfo(
-        ReferenceTypeInfo::Create(handle_cache_->GetThrowableClassHandle(), /* is_exact= */ false));
-  } else {
+  if (catch_info->IsValidTypeIndex()) {
     UpdateReferenceTypeInfo(instr,
                             catch_info->GetCatchTypeIndex(),
                             catch_info->GetCatchDexFile(),
                             /* is_exact= */ false);
+  } else {
+    instr->SetReferenceTypeInfo(
+        ReferenceTypeInfo::Create(handle_cache_->GetThrowableClassHandle(), /* is_exact= */ false));
   }
 }
 
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
index fd454f0..524bce0 100644
--- a/dex2oat/dex2oat_test.cc
+++ b/dex2oat/dex2oat_test.cc
@@ -1011,6 +1011,10 @@
 }
 
 TEST_F(Dex2oatWatchdogTest, TestWatchdogTrigger) {
+  // This test is frequently interrupted by timeout_dumper on host (x86);
+  // disable it while we investigate (b/121352534).
+  TEST_DISABLED_FOR_X86();
+
   // The watchdog is independent of dex2oat and will not delete intermediates. It is possible
   // that the compilation succeeds and the file is completely written by the time the watchdog
   // kills dex2oat (but the dex2oat threads must have been scheduled pretty badly).
diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc
index 1331fc3..15ced72 100644
--- a/dex2oat/linker/image_writer.cc
+++ b/dex2oat/linker/image_writer.cc
@@ -49,6 +49,7 @@
 #include "gc/heap-visit-objects-inl.h"
 #include "gc/heap.h"
 #include "gc/space/large_object_space.h"
+#include "gc/space/region_space.h"
 #include "gc/space/space-inl.h"
 #include "gc/verification.h"
 #include "handle_scope-inl.h"
@@ -2423,10 +2424,33 @@
   }
 
   // Calculate bin slot offsets.
-  for (ImageInfo& image_info : image_infos_) {
+  for (size_t oat_index = 0; oat_index < image_infos_.size(); ++oat_index) {
+    ImageInfo& image_info = image_infos_[oat_index];
     size_t bin_offset = image_objects_offset_begin_;
+    // Need to visit the objects in bin order since alignment requirements might change the
+    // section sizes.
+    // Avoid using ObjPtr since VisitObjects invalidates. This is safe since concurrent GC can not
+    // occur during image writing.
+    using BinPair = std::pair<BinSlot, mirror::Object*>;
+    std::vector<BinPair> objects;
+    heap->VisitObjects([&](mirror::Object* obj)
+        REQUIRES_SHARED(Locks::mutator_lock_) {
+      // Only visit the oat index for the current image.
+      if (IsImageObject(obj) && GetOatIndex(obj) == oat_index) {
+        objects.emplace_back(GetImageBinSlot(obj), obj);
+      }
+    });
+    std::sort(objects.begin(), objects.end(), [](const BinPair& a, const BinPair& b) -> bool {
+      if (a.first.GetBin() != b.first.GetBin()) {
+        return a.first.GetBin() < b.first.GetBin();
+      }
+      // Note that the index is really the relative offset in this case.
+      return a.first.GetIndex() < b.first.GetIndex();
+    });
+    auto it = objects.begin();
     for (size_t i = 0; i != kNumberOfBins; ++i) {
-      switch (static_cast<Bin>(i)) {
+      Bin bin = enum_cast<Bin>(i);
+      switch (bin) {
         case Bin::kArtMethodClean:
         case Bin::kArtMethodDirty: {
           bin_offset = RoundUp(bin_offset, method_alignment);
@@ -2445,13 +2469,49 @@
         }
       }
       image_info.bin_slot_offsets_[i] = bin_offset;
-      bin_offset += image_info.bin_slot_sizes_[i];
+
+      // If the bin is for mirror objects, assign the offsets since we may need to change sizes
+      // from alignment requirements.
+      if (i < static_cast<size_t>(Bin::kMirrorCount)) {
+        const size_t start_offset = bin_offset;
+        // Visit and assign offsets for all objects of the bin type.
+        while (it != objects.end() && it->first.GetBin() == bin) {
+          ObjPtr<mirror::Object> obj(it->second);
+          const size_t object_size = RoundUp(obj->SizeOf(), kObjectAlignment);
+          // If the object spans region bondaries, add padding objects between.
+          // TODO: Instead of adding padding, we should consider reordering the bins to reduce
+          // wasted space.
+          if (region_size_ != 0u) {
+            const size_t offset_after_header = bin_offset - sizeof(ImageHeader);
+            const size_t next_region = RoundUp(offset_after_header, region_size_);
+            if (offset_after_header != next_region &&
+                offset_after_header + object_size > next_region) {
+              // Add padding objects until aligned.
+              while (bin_offset - sizeof(ImageHeader) < next_region) {
+                image_info.padding_object_offsets_.push_back(bin_offset);
+                bin_offset += kObjectAlignment;
+                region_alignment_wasted_ += kObjectAlignment;
+                image_info.image_end_ += kObjectAlignment;
+              }
+              CHECK_EQ(bin_offset - sizeof(ImageHeader), next_region);
+            }
+          }
+          SetImageOffset(obj.Ptr(), bin_offset);
+          bin_offset = bin_offset + object_size;
+          ++it;
+        }
+        image_info.bin_slot_sizes_[i] = bin_offset - start_offset;
+      } else {
+        bin_offset += image_info.bin_slot_sizes_[i];
+      }
     }
     // NOTE: There may be additional padding between the bin slots and the intern table.
     DCHECK_EQ(image_info.image_end_,
               image_info.GetBinSizeSum(Bin::kMirrorCount) + image_objects_offset_begin_);
   }
 
+  VLOG(image) << "Space wasted for region alignment " << region_alignment_wasted_;
+
   // Calculate image offsets.
   size_t image_offset = 0;
   for (ImageInfo& image_info : image_infos_) {
@@ -2462,17 +2522,6 @@
     image_offset += image_info.image_size_;
   }
 
-  // Transform each object's bin slot into an offset which will be used to do the final copy.
-  {
-    auto unbin_objects_into_offset = [&](mirror::Object* obj)
-        REQUIRES_SHARED(Locks::mutator_lock_) {
-      if (IsImageObject(obj)) {
-        UnbinObjectsIntoOffset(obj);
-      }
-    };
-    heap->VisitObjects(unbin_objects_into_offset);
-  }
-
   size_t i = 0;
   for (ImageInfo& image_info : image_infos_) {
     image_info.image_roots_address_ = PointerToLowMemUInt32(GetImageAddress(image_roots[i].Get()));
@@ -2887,16 +2936,6 @@
   }
 }
 
-void ImageWriter::CopyAndFixupObjects() {
-  auto visitor = [&](Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
-    DCHECK(obj != nullptr);
-    CopyAndFixupObject(obj);
-  };
-  Runtime::Current()->GetHeap()->VisitObjects(visitor);
-  // We no longer need the hashcode map, values have already been copied to target objects.
-  saved_hashcode_map_.clear();
-}
-
 void ImageWriter::FixupPointerArray(mirror::Object* dst,
                                     mirror::PointerArray* arr,
                                     Bin array_type) {
@@ -2944,6 +2983,18 @@
   image_info.image_bitmap_->Set(dst);  // Mark the obj as live.
 
   const size_t n = obj->SizeOf();
+
+  if (kIsDebugBuild && region_size_ != 0u) {
+    const size_t offset_after_header = offset - sizeof(ImageHeader);
+    const size_t next_region = RoundUp(offset_after_header, region_size_);
+    if (offset_after_header != next_region) {
+      // If the object is not on a region bondary, it must not be cross region.
+      CHECK_LT(offset_after_header, next_region)
+          << "offset_after_header=" << offset_after_header << " size=" << n;
+      CHECK_LE(offset_after_header + n, next_region)
+          << "offset_after_header=" << offset_after_header << " size=" << n;
+    }
+  }
   DCHECK_LE(offset + n, image_info.image_.Size());
   memcpy(dst, src, n);
 
@@ -2973,7 +3024,6 @@
       const {}
   void VisitRoot(mirror::CompressedReference<mirror::Object>* root ATTRIBUTE_UNUSED) const {}
 
-
   void operator()(ObjPtr<Object> obj, MemberOffset offset, bool is_static ATTRIBUTE_UNUSED) const
       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_) {
     ObjPtr<Object> ref = obj->GetFieldObject<Object, kVerifyNone>(offset);
@@ -2994,6 +3044,25 @@
   mirror::Object* const copy_;
 };
 
+void ImageWriter::CopyAndFixupObjects() {
+  auto visitor = [&](Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
+    DCHECK(obj != nullptr);
+    CopyAndFixupObject(obj);
+  };
+  Runtime::Current()->GetHeap()->VisitObjects(visitor);
+  // Copy the padding objects since they are required for in order traversal of the image space.
+  for (const ImageInfo& image_info : image_infos_) {
+    for (const size_t offset : image_info.padding_object_offsets_) {
+      auto* dst = reinterpret_cast<Object*>(image_info.image_.Begin() + offset);
+      dst->SetClass<kVerifyNone>(GetImageAddress(GetClassRoot<mirror::Object>().Ptr()));
+      dst->SetLockWord<kVerifyNone>(LockWord::Default(), /*as_volatile=*/ false);
+      image_info.image_bitmap_->Set(dst);  // Mark the obj as live.
+    }
+  }
+  // We no longer need the hashcode map, values have already been copied to target objects.
+  saved_hashcode_map_.clear();
+}
+
 class ImageWriter::FixupClassVisitor final : public FixupVisitor {
  public:
   FixupClassVisitor(ImageWriter* image_writer, Object* copy)
@@ -3572,6 +3641,10 @@
   CHECK_EQ(compiler_options.IsBootImage(),
            Runtime::Current()->GetHeap()->GetBootImageSpaces().empty())
       << "Compiling a boot image should occur iff there are no boot image spaces loaded";
+  if (compiler_options_.IsAppImage()) {
+    // Make sure objects are not crossing region boundaries for app images.
+    region_size_ = gc::space::RegionSpace::kRegionSize;
+  }
 }
 
 ImageWriter::ImageInfo::ImageInfo()
diff --git a/dex2oat/linker/image_writer.h b/dex2oat/linker/image_writer.h
index b680265..8896e07 100644
--- a/dex2oat/linker/image_writer.h
+++ b/dex2oat/linker/image_writer.h
@@ -279,7 +279,7 @@
 
    private:
     // Must be the same size as LockWord, any larger and we would truncate the data.
-    const uint32_t lockword_;
+    uint32_t lockword_;
   };
 
   struct ImageInfo {
@@ -397,6 +397,9 @@
 
     // Class table associated with this image for serialization.
     std::unique_ptr<ClassTable> class_table_;
+
+    // Padding objects to ensure region alignment (if required).
+    std::vector<size_t> padding_object_offsets_;
   };
 
   // We use the lock word to store the offset of the object in the image.
@@ -798,6 +801,12 @@
   // Set of objects known to be dirty in the image. Can be nullptr if there are none.
   const HashSet<std::string>* dirty_image_objects_;
 
+  // Objects are guaranteed to not cross the region size boundary.
+  size_t region_size_ = 0u;
+
+  // Region alignment bytes wasted.
+  size_t region_alignment_wasted_ = 0u;
+
   class ImageFileGuard;
   class FixupClassVisitor;
   class FixupRootVisitor;
diff --git a/dex2oat/linker/oat_writer.h b/dex2oat/linker/oat_writer.h
index cc0e83a..48215bb 100644
--- a/dex2oat/linker/oat_writer.h
+++ b/dex2oat/linker/oat_writer.h
@@ -19,6 +19,7 @@
 
 #include <stdint.h>
 #include <cstddef>
+#include <list>
 #include <memory>
 #include <vector>
 
diff --git a/dexlayout/Android.bp b/dexlayout/Android.bp
index 24ee5f8..e914738 100644
--- a/dexlayout/Android.bp
+++ b/dexlayout/Android.bp
@@ -26,9 +26,33 @@
         "dex_writer.cc",
     ],
     export_include_dirs: ["."],
-    shared_libs: [
-        "libbase",
-    ],
+    target: {
+        android: {
+            shared_libs: [
+                "libdexfile",
+                "libartbase",
+                "libprofile",
+                "libbase",
+            ],
+        },
+        not_windows: {
+            shared_libs: [
+                "libdexfile",
+                "libartbase",
+                "libprofile",
+                "libbase",
+            ],
+        },
+        windows: {
+            cflags: ["-Wno-thread-safety"],
+            static_libs: [
+                "libdexfile",
+                "libartbase",
+                "libprofile",
+                "libbase",
+            ],
+        },
+    },
     static_libs: ["libz"],
 }
 
@@ -46,18 +70,18 @@
         "libart-dexlayout-defaults",
         "dex2oat-pgo-defaults",
     ],
-    shared_libs: [
-        "libdexfile",
-        "libartbase",
-        "libprofile",
-    ],
-
     target: {
         android: {
             lto: {
                  thin: true,
             },
         },
+        windows: {
+            enabled: true,
+            shared: {
+                enabled: false,
+            },
+        },
     },
 }
 
@@ -118,6 +142,29 @@
 }
 
 art_cc_binary {
+    name: "dexlayouts",
+    defaults: [
+        "dexlayout-defaults",
+        "libart-dexlayout_static_defaults",
+        "libprofile_static_defaults",
+        "libdexfile_static_defaults",
+        "libartbase_static_defaults",
+    ],
+    srcs: ["dexlayout_main.cc"],
+    host_supported: true,
+    device_supported: false,
+    target: {
+        darwin: {
+            enabled: false,
+        },
+        windows: {
+            enabled: true,
+            cflags: ["-Wno-thread-safety"],
+        },
+    },
+}
+
+art_cc_binary {
     name: "dexlayoutd",
     defaults: [
         "art_debug_defaults",
diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc
index 32122eb..ef2c9e4 100644
--- a/dexlayout/dexlayout.cc
+++ b/dexlayout/dexlayout.cc
@@ -24,7 +24,6 @@
 
 #include <inttypes.h>
 #include <stdio.h>
-#include <sys/mman.h>  // For the PROT_* and MAP_* constants.
 
 #include <iostream>
 #include <memory>
@@ -36,6 +35,7 @@
 #include "base/logging.h"  // For VLOG_IS_ON.
 #include "base/hiddenapi_flags.h"
 #include "base/mem_map.h"
+#include "base/mman.h"  // For the PROT_* and MAP_* constants.
 #include "base/os.h"
 #include "base/utils.h"
 #include "dex/art_dex_file_loader.h"
diff --git a/dexlayout/dexlayout_main.cc b/dexlayout/dexlayout_main.cc
index 41b60da..2163f89 100644
--- a/dexlayout/dexlayout_main.cc
+++ b/dexlayout/dexlayout_main.cc
@@ -190,7 +190,12 @@
   // Open profile file.
   std::unique_ptr<ProfileCompilationInfo> profile_info;
   if (options.profile_file_name_) {
-    int profile_fd = open(options.profile_file_name_, O_RDONLY | O_CLOEXEC);
+#ifdef _WIN32
+    int flags = O_RDONLY;
+#else
+    int flags = O_RDONLY | O_CLOEXEC;
+#endif
+    int profile_fd = open(options.profile_file_name_, flags);
     if (profile_fd < 0) {
       PLOG(ERROR) << "Can't open " << options.profile_file_name_;
       return 1;
@@ -201,6 +206,7 @@
       return 1;
     }
   }
+  PLOG(INFO) << "After opening profile file";
 
   // Create DexLayout instance.
   DexLayout dex_layout(options, profile_info.get(), out_file, /*header=*/ nullptr);
diff --git a/dexlist/Android.bp b/dexlist/Android.bp
index 217a024..356791c 100644
--- a/dexlist/Android.bp
+++ b/dexlist/Android.bp
@@ -24,6 +24,26 @@
     ],
 }
 
+art_cc_binary {
+    name: "dexlists",
+    defaults: [
+        "art_defaults",
+        "libartbase_static_defaults",
+        "libdexfile_static_defaults",
+    ],
+    host_supported: true,
+    srcs: ["dexlist.cc"],
+    device_supported: false,
+    target: {
+        darwin: {
+            enabled: false,
+        },
+        windows: {
+            enabled: true,
+        },
+    },
+}
+
 art_cc_test {
     name: "art_dexlist_tests",
     defaults: [
diff --git a/dexoptanalyzer/dexoptanalyzer.cc b/dexoptanalyzer/dexoptanalyzer.cc
index acf0f94..92850f7 100644
--- a/dexoptanalyzer/dexoptanalyzer.cc
+++ b/dexoptanalyzer/dexoptanalyzer.cc
@@ -202,11 +202,7 @@
             Usage("Invalid --zip-fd %d", zip_fd_);
           }
       } else if (option.starts_with("--class-loader-context=")) {
-        std::string context_str = option.substr(strlen("--class-loader-context=")).ToString();
-        class_loader_context_ = ClassLoaderContext::Create(context_str);
-        if (class_loader_context_ == nullptr) {
-          Usage("Invalid --class-loader-context '%s'", context_str.c_str());
-        }
+        context_str_ = option.substr(strlen("--class-loader-context=")).ToString();
       } else {
         Usage("Unknown argument '%s'", option.data());
       }
@@ -264,6 +260,17 @@
     }
     std::unique_ptr<Runtime> runtime(Runtime::Current());
 
+    // Only when the runtime is created can we create the class loader context: the
+    // class loader context will open dex file and use the MemMap global lock that the
+    // runtime owns.
+    std::unique_ptr<ClassLoaderContext> class_loader_context;
+    if (!context_str_.empty()) {
+      class_loader_context = ClassLoaderContext::Create(context_str_);
+      if (class_loader_context == nullptr) {
+        Usage("Invalid --class-loader-context '%s'", context_str_.c_str());
+      }
+    }
+
     std::unique_ptr<OatFileAssistant> oat_file_assistant;
     oat_file_assistant = std::make_unique<OatFileAssistant>(dex_file_.c_str(),
                                                             isa_,
@@ -279,7 +286,7 @@
     }
 
     int dexoptNeeded = oat_file_assistant->GetDexOptNeeded(
-        compiler_filter_, assume_profile_changed_, downgrade_, class_loader_context_.get());
+        compiler_filter_, assume_profile_changed_, downgrade_, class_loader_context.get());
 
     // Convert OatFileAssitant codes to dexoptanalyzer codes.
     switch (dexoptNeeded) {
@@ -300,7 +307,7 @@
   std::string dex_file_;
   InstructionSet isa_;
   CompilerFilter::Filter compiler_filter_;
-  std::unique_ptr<ClassLoaderContext> class_loader_context_;
+  std::string context_str_;
   bool assume_profile_changed_;
   bool downgrade_;
   std::string image_;
diff --git a/dexoptanalyzer/dexoptanalyzer_test.cc b/dexoptanalyzer/dexoptanalyzer_test.cc
index f6fd1fb..7b6b36c 100644
--- a/dexoptanalyzer/dexoptanalyzer_test.cc
+++ b/dexoptanalyzer/dexoptanalyzer_test.cc
@@ -36,7 +36,8 @@
 
   int Analyze(const std::string& dex_file,
               CompilerFilter::Filter compiler_filter,
-              bool assume_profile_changed) {
+              bool assume_profile_changed,
+              const std::string& class_loader_context) {
     std::string dexoptanalyzer_cmd = GetDexoptAnalyzerCmd();
     std::vector<std::string> argv_str;
     argv_str.push_back(dexoptanalyzer_cmd);
@@ -52,6 +53,9 @@
     argv_str.push_back(GetClassPathOption("-Xbootclasspath-locations:", GetLibCoreDexLocations()));
     argv_str.push_back("--image=" + GetImageLocation());
     argv_str.push_back("--android-data=" + android_data_);
+    if (!class_loader_context.empty()) {
+      argv_str.push_back("--class-loader-context=" + class_loader_context);
+    }
 
     std::string error;
     return ExecAndReturnCode(argv_str, &error);
@@ -74,8 +78,10 @@
   void Verify(const std::string& dex_file,
               CompilerFilter::Filter compiler_filter,
               bool assume_profile_changed = false,
-              bool downgrade = false) {
-    int dexoptanalyzerResult = Analyze(dex_file, compiler_filter, assume_profile_changed);
+              bool downgrade = false,
+              const std::string& class_loader_context = "") {
+    int dexoptanalyzerResult = Analyze(
+        dex_file, compiler_filter, assume_profile_changed, class_loader_context);
     dexoptanalyzerResult = DexoptanalyzerToOatFileAssistant(dexoptanalyzerResult);
     OatFileAssistant oat_file_assistant(dex_file.c_str(), kRuntimeISA, /*load_executable=*/ false);
     int assistantResult = oat_file_assistant.GetDexOptNeeded(
@@ -305,4 +311,22 @@
   Verify(dex_location, CompilerFilter::kSpeed);
 }
 
+// Case: We have a DEX file and up-to-date OAT file for it, and we check with
+// a class loader context.
+TEST_F(DexoptAnalyzerTest, ClassLoaderContext) {
+  std::string dex_location1 = GetScratchDir() + "/DexToAnalyze.jar";
+  std::string odex_location1 = GetOdexDir() + "/DexToAnalyze.odex";
+  std::string dex_location2 = GetScratchDir() + "/DexInContext.jar";
+  Copy(GetDexSrc1(), dex_location1);
+  Copy(GetDexSrc2(), dex_location2);
+
+  std::string class_loader_context = "PCL[" + dex_location2 + "]";
+  std::string class_loader_context_option = "--class-loader-context=PCL[" + dex_location2 + "]";
+
+  // Generate the odex to get the class loader context also open the dex files.
+  GenerateOdexForTest(dex_location1, odex_location1, CompilerFilter::kSpeed, /* compilation_reason= */ nullptr, /* extra_args= */ { class_loader_context_option });
+
+  Verify(dex_location1, CompilerFilter::kSpeed, false, false, class_loader_context);
+}
+
 }  // namespace art
diff --git a/libart_fake/Android.mk b/libart_fake/Android.mk
deleted file mode 100644
index 96e6a14..0000000
--- a/libart_fake/Android.mk
+++ /dev/null
@@ -1,35 +0,0 @@
-# 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.
-#
-
-LOCAL_PATH := $(my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libart_fake
-LOCAL_INSTALLED_MODULE_STEM := libart.so
-LOCAL_SDK_VERSION := 9
-LOCAL_CPP_EXTENSION := .cc
-LOCAL_SRC_FILES := fake.cc
-LOCAL_CFLAGS := -Wall -Werror
-LOCAL_SHARED_LIBRARIES := liblog
-
-ifdef TARGET_2ND_ARCH
-    LOCAL_MODULE_PATH_32 := $(TARGET_OUT)/fake-libs
-    LOCAL_MODULE_PATH_64 := $(TARGET_OUT)/fake-libs64
-else
-    LOCAL_MODULE_PATH := $(TARGET_OUT)/fake-libs
-endif
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/libart_fake/README.md b/libart_fake/README.md
deleted file mode 100644
index 6e3621e..0000000
--- a/libart_fake/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
-libart_fake
-====
-
-A fake libart made to satisfy some misbehaving apps that will attempt to link
-against libart.so.
diff --git a/libart_fake/fake.cc b/libart_fake/fake.cc
deleted file mode 100644
index 8842421..0000000
--- a/libart_fake/fake.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 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.
- */
-
-#define LOG_TAG "libart_fake"
-
-#include <android/log.h>
-
-#define LOGIT(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
-namespace art {
-class Dbg {
- public:
-  void SuspendVM();
-  void ResumeVM();
-};
-
-class FaultManager {
- public:
-  void EnsureArtActionInFrontOfSignalChain();
-};
-
-void Dbg::SuspendVM() {
-  LOGIT("Linking to and calling into libart.so internal functions is not supported. "
-        "This call to '%s' is being ignored.", __func__);
-}
-void Dbg::ResumeVM() {
-  LOGIT("Linking to and calling into libart.so internal functions is not supported. "
-        "This call to '%s' is being ignored.", __func__);
-}
-void FaultManager::EnsureArtActionInFrontOfSignalChain() {
-  LOGIT("Linking to and calling into libart.so internal functions is not supported. "
-        "This call to '%s' is being ignored.", __func__);
-}
-};  // namespace art
diff --git a/libartbase/Android.bp b/libartbase/Android.bp
index 0fcd6a5..509b072 100644
--- a/libartbase/Android.bp
+++ b/libartbase/Android.bp
@@ -24,6 +24,7 @@
         "base/arena_allocator.cc",
         "base/arena_bit_vector.cc",
         "base/bit_vector.cc",
+        "base/enums.cc",
         "base/file_magic.cc",
         "base/file_utils.cc",
         "base/hex_dump.cc",
@@ -64,6 +65,7 @@
                 // For common macros.
                 "libbase",
             ],
+            export_shared_lib_headers: ["libbase"],
             // Exclude the version script from Darwin host since it's not
             // supported by the linker there. That means ASan checks on Darwin
             // might trigger ODR violations.
@@ -82,12 +84,16 @@
                 // For common macros.
                 "libbase",
             ],
+            export_shared_lib_headers: ["libbase"],
         },
         linux_glibc: {
             version_script: "libartbase.map",
         },
         windows: {
             version_script: "libartbase.map",
+            srcs: [
+                "base/mem_map_windows.cc",
+            ],
             static_libs: [
                 "libziparchive",
                 "libz",
@@ -97,6 +103,7 @@
                 // For common macros.
                 "libbase",
             ],
+            export_static_lib_headers: ["libbase"],
             cflags: ["-Wno-thread-safety"],
         },
     },
@@ -115,7 +122,6 @@
     // ART's macros.h depends on libbase's macros.h.
     // Note: runtime_options.h depends on cmdline. But we don't really want to export this
     //       generically. dex2oat takes care of it itself.
-    export_shared_lib_headers: ["libbase"],
 }
 
 cc_defaults {
@@ -148,7 +154,6 @@
     srcs: [
         "arch/instruction_set.h",
         "base/allocator.h",
-        "base/callee_save_type.h",
         "base/unix_file/fd_file.h",
     ],
     output_extension: "operator_out.cc",
diff --git a/libartbase/base/enums.cc b/libartbase/base/enums.cc
new file mode 100644
index 0000000..3f28232
--- /dev/null
+++ b/libartbase/base/enums.cc
@@ -0,0 +1,32 @@
+/*
+ * 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 "enums.h"
+
+#include <ostream>
+
+namespace art {
+
+std::ostream& operator<<(std::ostream& os, const PointerSize& rhs) {
+  switch (rhs) {
+    case PointerSize::k32: os << "k32"; break;
+    case PointerSize::k64: os << "k64"; break;
+    default: os << "PointerSize[" << static_cast<int>(rhs) << "]"; break;
+  }
+  return os;
+}
+
+}  // namespace art
diff --git a/libartbase/base/enums.h b/libartbase/base/enums.h
index ad5578f..c5fb880 100644
--- a/libartbase/base/enums.h
+++ b/libartbase/base/enums.h
@@ -18,7 +18,7 @@
 #define ART_LIBARTBASE_BASE_ENUMS_H_
 
 #include <cstddef>
-#include <ostream>
+#include <iosfwd>
 
 namespace art {
 
@@ -27,14 +27,7 @@
   k64 = 8
 };
 
-inline std::ostream& operator<<(std::ostream& os, const PointerSize& rhs) {
-  switch (rhs) {
-    case PointerSize::k32: os << "k32"; break;
-    case PointerSize::k64: os << "k64"; break;
-    default: os << "PointerSize[" << static_cast<int>(rhs) << "]"; break;
-  }
-  return os;
-}
+std::ostream& operator<<(std::ostream& os, const PointerSize& rhs);
 
 static constexpr PointerSize kRuntimePointerSize = sizeof(void*) == 8U
                                                        ? PointerSize::k64
diff --git a/libartbase/base/globals.h b/libartbase/base/globals.h
index 2a2a737..97eae63 100644
--- a/libartbase/base/globals.h
+++ b/libartbase/base/globals.h
@@ -38,20 +38,6 @@
 // compile-time constant so the compiler can generate better code.
 static constexpr int kPageSize = 4096;
 
-// Size of Dex virtual registers.
-static constexpr size_t kVRegSize = 4;
-
-// Returns whether the given memory offset can be used for generating
-// an implicit null check.
-static inline bool CanDoImplicitNullCheckOn(uintptr_t offset) {
-  return offset < kPageSize;
-}
-
-// Required object alignment
-static constexpr size_t kObjectAlignmentShift = 3;
-static constexpr size_t kObjectAlignment = 1u << kObjectAlignmentShift;
-static constexpr size_t kLargeObjectAlignment = kPageSize;
-
 // Clion, clang analyzer, etc can falsely believe that "if (kIsDebugBuild)" always
 // returns the same value. By wrapping into a call to another constexpr function, we force it
 // to realize that is not actually always evaluating to the same value.
@@ -117,48 +103,6 @@
 static constexpr bool kHostStaticBuildEnabled = false;
 #endif
 
-// Garbage collector constants.
-static constexpr bool kMovingCollector = true;
-static constexpr bool kMarkCompactSupport = false && kMovingCollector;
-// True if we allow moving classes.
-static constexpr bool kMovingClasses = !kMarkCompactSupport;
-// If true, enable generational collection when using the Concurrent Copying
-// (CC) collector, i.e. use sticky-bit CC for minor collections and (full) CC
-// for major collections.
-//
-// Generational CC collection is currently only compatible with Baker read
-// barriers.
-#if defined(ART_USE_GENERATIONAL_CC) && defined(ART_READ_BARRIER_TYPE_IS_BAKER)
-static constexpr bool kEnableGenerationalConcurrentCopyingCollection = true;
-#else
-static constexpr bool kEnableGenerationalConcurrentCopyingCollection = false;
-#endif
-
-// If true, enable the tlab allocator by default.
-#ifdef ART_USE_TLAB
-static constexpr bool kUseTlab = true;
-#else
-static constexpr bool kUseTlab = false;
-#endif
-
-// Kinds of tracing clocks.
-enum class TraceClockSource {
-  kThreadCpu,
-  kWall,
-  kDual,  // Both wall and thread CPU clocks.
-};
-
-#if defined(__linux__)
-static constexpr TraceClockSource kDefaultTraceClockSource = TraceClockSource::kDual;
-#else
-static constexpr TraceClockSource kDefaultTraceClockSource = TraceClockSource::kWall;
-#endif
-
-static constexpr bool kDefaultMustRelocate = true;
-
-// Size of a heap reference.
-static constexpr size_t kHeapReferenceSize = sizeof(uint32_t);
-
 }  // namespace art
 
 #endif  // ART_LIBARTBASE_BASE_GLOBALS_H_
diff --git a/libartbase/base/logging.h b/libartbase/base/logging.h
index 9ded082..484db87 100644
--- a/libartbase/base/logging.h
+++ b/libartbase/base/logging.h
@@ -17,9 +17,6 @@
 #ifndef ART_LIBARTBASE_BASE_LOGGING_H_
 #define ART_LIBARTBASE_BASE_LOGGING_H_
 
-#include <ostream>
-#include <sstream>
-
 #include "android-base/logging.h"
 #include "macros.h"
 
diff --git a/libartbase/base/mem_map_windows.cc b/libartbase/base/mem_map_windows.cc
new file mode 100644
index 0000000..84e14ea
--- /dev/null
+++ b/libartbase/base/mem_map_windows.cc
@@ -0,0 +1,140 @@
+/*
+ * 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.
+ */
+
+#include "mem_map.h"
+
+#include <windows.h>
+
+#include "android-base/logging.h"
+#include "android-base/stringprintf.h"
+#include "android-base/mapped_file.h"
+#ifdef PROT_READ
+#undef PROT_READ
+#endif
+#ifdef PROT_WRITE
+#undef PROT_WRITE
+#endif
+#include "mman.h"
+
+namespace art {
+
+using android::base::MappedFile;
+using android::base::StringPrintf;
+
+static off_t allocation_granularity;
+
+void MemMap::TargetMMapInit() {
+  SYSTEM_INFO si;
+  GetSystemInfo(&si);
+  allocation_granularity = si.dwAllocationGranularity;
+}
+
+void* MemMap::TargetMMap(void* start, size_t len, int prot, int flags, int fd, off_t fd_off) {
+  UNUSED(start);
+  size_t padding = fd_off % allocation_granularity;
+  off_t file_offset = fd_off - padding;
+  off_t map_length = len + padding;
+
+  // Only read and write permissions are supported.
+  if ((prot != PROT_READ) && (prot != (PROT_READ | PROT_WRITE))) {
+    PLOG(ERROR) << "Protection or flag error was not supported.";
+    errno = EINVAL;
+    return MAP_FAILED;
+  }
+  // Fixed is not currently supported either.
+  // TODO(sehr): add MAP_FIXED support.
+  if ((flags & MAP_FIXED) != 0) {
+    PLOG(ERROR) << "MAP_FIXED not supported.";
+    errno = EINVAL;
+    return MAP_FAILED;
+  }
+
+  // Compute the Windows access flags for the two APIs from the PROTs and MAPs.
+  DWORD map_access = 0;
+  DWORD view_access = 0;
+  if ((prot & PROT_WRITE) != 0) {
+    map_access = PAGE_READWRITE;
+    if (((flags & MAP_SHARED) != 0) && ((flags & MAP_PRIVATE) == 0)) {
+      view_access = FILE_MAP_ALL_ACCESS;
+    } else if (((flags & MAP_SHARED) == 0) && ((flags & MAP_PRIVATE) != 0)) {
+      view_access = FILE_MAP_COPY | FILE_MAP_READ;
+    } else {
+      PLOG(ERROR) << "MAP_PRIVATE and MAP_SHARED inconsistently set.";
+      errno = EINVAL;
+      return MAP_FAILED;
+    }
+  } else {
+    map_access = PAGE_READONLY;
+    view_access = FILE_MAP_READ;
+  }
+
+  // MapViewOfFile does not like to see a size greater than the file size of the
+  // underlying file object, unless the underlying file object is writable.  If
+  // the mapped region would go beyond the end of the underlying file, use zero,
+  // as this indicates the physical size.
+  HANDLE file_handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
+  LARGE_INTEGER file_length;
+  if (!::GetFileSizeEx(file_handle, &file_length)) {
+    PLOG(ERROR) << "Couldn't get file size.";
+    errno = EINVAL;
+    return MAP_FAILED;
+  }
+  if (((map_access & PAGE_READONLY) != 0) &&
+      file_offset + map_length > file_length.QuadPart) {
+    map_length = 0;
+  }
+
+  // Create a file mapping object that will be used to access the file.
+  HANDLE handle = ::CreateFileMapping(reinterpret_cast<HANDLE>(_get_osfhandle(fd)),
+                                      nullptr,
+                                      map_access,
+                                      0,
+                                      0,
+                                      nullptr);
+  if (handle == nullptr) {
+    DWORD error = ::GetLastError();
+    PLOG(ERROR) << StringPrintf("Couldn't create file mapping %lx.", error);
+    errno = EINVAL;
+    return MAP_FAILED;
+  }
+
+  // Map the file into the process address space.
+  DWORD offset_low = static_cast<DWORD>(file_offset & 0xffffffffU);
+#ifdef _WIN64
+  DWORD offset_high = static_cast<DWORD>(file_offset >> 32);
+#else
+  DWORD offset_high = static_cast<DWORD>(0);
+#endif
+  void* view_address = MapViewOfFile(handle, view_access, offset_high, offset_low, map_length);
+  if (view_address == nullptr) {
+    DWORD error = ::GetLastError();
+    PLOG(ERROR) << StringPrintf("Couldn't create file view %lx.", error);
+    ::CloseHandle(handle);
+    errno = EINVAL;
+    return MAP_FAILED;
+  }
+
+  return view_address;
+}
+
+int MemMap::TargetMUnmap(void* start, size_t len) {
+  // TODO(sehr): implement unmap.
+  UNUSED(start);
+  UNUSED(len);
+  return 0;
+}
+
+}  // namespace art
diff --git a/libartbase/base/mman.h b/libartbase/base/mman.h
index bd63f65..b56edfc 100644
--- a/libartbase/base/mman.h
+++ b/libartbase/base/mman.h
@@ -20,19 +20,18 @@
 #ifdef _WIN32
 
 // There is no sys/mman.h in mingw.
-// As these are just placeholders for the APIs, all values are stubbed out.
 
-#define PROT_READ      0        // 0x1
-#define PROT_WRITE     0        // 0x2
-#define PROT_EXEC      0        // 0x4
-#define PROT_NONE      0        // 0x0
+#define PROT_READ      0x1
+#define PROT_WRITE     0x2
+#define PROT_EXEC      0x4
+#define PROT_NONE      0x0
 
-#define MAP_SHARED     0        // 0x01
-#define MAP_PRIVATE    0        // 0x02
+#define MAP_SHARED     0x01
+#define MAP_PRIVATE    0x02
 
-#define MAP_FAILED     nullptr  // ((void*) -1)
-#define MAP_FIXED      0        // 0x10
-#define MAP_ANONYMOUS  0        // 0x20
+#define MAP_FAILED     ((void*) -1)
+#define MAP_FIXED      0x10
+#define MAP_ANONYMOUS  0x20
 
 #else
 
diff --git a/libdexfile/Android.bp b/libdexfile/Android.bp
index 9c48aa2..2f56a3d 100644
--- a/libdexfile/Android.bp
+++ b/libdexfile/Android.bp
@@ -176,6 +176,36 @@
     },
 }
 
+art_cc_test {
+    name: "art_libdexfile_tests",
+    defaults: [
+        "art_gtest_defaults",
+    ],
+    srcs: [
+        "dex/art_dex_file_loader_test.cc",
+        "dex/class_accessor_test.cc",
+        "dex/code_item_accessors_test.cc",
+        "dex/compact_dex_file_test.cc",
+        "dex/compact_offset_table_test.cc",
+        "dex/descriptors_names_test.cc",
+        "dex/test_dex_file_builder_test.cc",
+        "dex/dex_file_loader_test.cc",
+        "dex/dex_file_verifier_test.cc",
+        "dex/dex_instruction_test.cc",
+        "dex/primitive_test.cc",
+        "dex/string_reference_test.cc",
+        "dex/type_lookup_table_test.cc",
+        "dex/utf_test.cc",
+    ],
+    shared_libs: [
+        "libbacktrace",
+        "libziparchive",
+    ],
+    include_dirs: [
+        "external/zlib",
+    ],
+}
+
 cc_library_headers {
     name: "libdexfile_external_headers",
     host_supported: true,
@@ -227,6 +257,16 @@
     },
 }
 
+art_cc_test {
+    name: "art_libdexfile_external_tests",
+    host_supported: true,
+    test_per_src: true,  // For consistency with other ART gtests.
+    srcs: [
+        "external/dex_file_ext_c_test.c",
+    ],
+    header_libs: ["libdexfile_external_headers"],
+}
+
 // Support library with a C++ API for accessing the libdexfile API for external
 // (non-ART) users. They should link to their own instance of this (either
 // statically or through linker namespaces).
@@ -242,31 +282,16 @@
 }
 
 art_cc_test {
-    name: "art_libdexfile_tests",
-    defaults: [
-        "art_gtest_defaults",
-    ],
+    name: "art_libdexfile_support_tests",
+    host_supported: true,
+    test_per_src: true,  // For consistency with other ART gtests.
     srcs: [
-        "dex/art_dex_file_loader_test.cc",
-        "dex/class_accessor_test.cc",
-        "dex/code_item_accessors_test.cc",
-        "dex/compact_dex_file_test.cc",
-        "dex/compact_offset_table_test.cc",
-        "dex/descriptors_names_test.cc",
-        "dex/test_dex_file_builder_test.cc",
-        "dex/dex_file_loader_test.cc",
-        "dex/dex_file_verifier_test.cc",
-        "dex/dex_instruction_test.cc",
-        "dex/primitive_test.cc",
-        "dex/string_reference_test.cc",
-        "dex/type_lookup_table_test.cc",
-        "dex/utf_test.cc",
+        "external/dex_file_supp_test.cc",
     ],
     shared_libs: [
-        "libbacktrace",
-        "libziparchive",
-    ],
-    include_dirs: [
-        "external/zlib",
+        "libartbase",
+        "libbase",
+        "libdexfile_external",
+        "libdexfile_support",
     ],
 }
diff --git a/libdexfile/dex/dex_file.cc b/libdexfile/dex/dex_file.cc
index 5c100e6..d3cdf13 100644
--- a/libdexfile/dex/dex_file.cc
+++ b/libdexfile/dex/dex_file.cc
@@ -23,6 +23,7 @@
 #include <zlib.h>
 
 #include <memory>
+#include <ostream>
 #include <sstream>
 #include <type_traits>
 
diff --git a/libdexfile/dex/dex_file_types.h b/libdexfile/dex/dex_file_types.h
index d4fb3de..ecc0482 100644
--- a/libdexfile/dex/dex_file_types.h
+++ b/libdexfile/dex/dex_file_types.h
@@ -17,8 +17,9 @@
 #ifndef ART_LIBDEXFILE_DEX_DEX_FILE_TYPES_H_
 #define ART_LIBDEXFILE_DEX_DEX_FILE_TYPES_H_
 
+#include <iosfwd>
 #include <limits>
-#include <ostream>
+#include <utility>
 
 namespace art {
 namespace dex {
diff --git a/libdexfile/external/dex_file_ext.cc b/libdexfile/external/dex_file_ext.cc
index 5c353b5..e1b7874 100644
--- a/libdexfile/external/dex_file_ext.cc
+++ b/libdexfile/external/dex_file_ext.cc
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include "art_api/dex_file_external.h"
+
 #include <inttypes.h>
 #include <stdint.h>
 #include <sys/mman.h>
@@ -39,18 +41,9 @@
 #include <dex/dex_file-inl.h>
 #include <dex/dex_file_loader.h>
 
-#include "art_api/ext_dex_file.h"
-
-extern "C" class ExtDexFileString {
- public:
-  const std::string str_;
-};
-
 namespace art {
 namespace {
 
-const ExtDexFileString empty_string{""};
-
 struct MethodCacheEntry {
   int32_t offset;  // Offset relative to the start of the dex file header.
   int32_t len;
@@ -77,11 +70,17 @@
 
 extern "C" {
 
-const ExtDexFileString* ExtDexFileMakeString(const char* str) {
-  if (str[0] == '\0') {
-    return &art::empty_string;
+struct ExtDexFileString {
+  const std::string str_;
+};
+
+static const ExtDexFileString empty_string{""};
+
+const ExtDexFileString* ExtDexFileMakeString(const char* str, size_t size) {
+  if (size == 0) {
+    return &empty_string;
   }
-  return new ExtDexFileString{str};
+  return new ExtDexFileString{std::string(str, size)};
 }
 
 const char* ExtDexFileGetString(const ExtDexFileString* ext_string, /*out*/ size_t* size) {
@@ -92,14 +91,15 @@
 
 void ExtDexFileFreeString(const ExtDexFileString* ext_string) {
   DCHECK(ext_string != nullptr);
-  if (ext_string != &art::empty_string) {
+  if (ext_string != &empty_string) {
     delete (ext_string);
   }
 }
 
 // Wraps DexFile to add the caching needed by the external interface. This is
 // what gets passed over as ExtDexFile*.
-class ExtDexFile {
+struct ExtDexFile {
+ private:
   // Method cache for GetMethodInfoForOffset. This is populated as we iterate
   // sequentially through the class defs. MethodCacheEntry.name is only set for
   // methods returned by GetMethodInfoForOffset.
@@ -226,7 +226,10 @@
 
   if (length < offset + sizeof(art::DexFile::Header)) {
     *ext_error_msg = new ExtDexFileString{android::base::StringPrintf(
-        "Offset %" PRId64 " too large for '%s' of size %zu", int64_t{offset}, location, length)};
+        "Offset %" PRId64 " too large for '%s' of size %zu",
+        int64_t{offset},
+        location,
+        length)};
     return false;
   }
 
@@ -282,6 +285,7 @@
 
 int ExtDexFileGetMethodInfoForOffset(ExtDexFile* ext_dex_file,
                                      int64_t dex_offset,
+                                     int with_signature,
                                      /*out*/ ExtDexFileMethodInfo* method_info) {
   if (!ext_dex_file->dex_file_->IsInDataSection(ext_dex_file->dex_file_->Begin() + dex_offset)) {
     return false;  // The DEX offset is not within the bytecode of this dex file.
@@ -304,7 +308,7 @@
     method_info->offset = entry->offset;
     method_info->len = entry->len;
     method_info->name =
-        new ExtDexFileString{ext_dex_file->dex_file_->PrettyMethod(entry->index, false)};
+        new ExtDexFileString{ext_dex_file->dex_file_->PrettyMethod(entry->index, with_signature)};
     return true;
   }
 
diff --git a/libdexfile/external/dex_file_ext_c_test.c b/libdexfile/external/dex_file_ext_c_test.c
new file mode 100644
index 0000000..c448a16
--- /dev/null
+++ b/libdexfile/external/dex_file_ext_c_test.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 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 <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+/* The main purpose of this test is to ensure this C header compiles in C, so
+ * that no C++ features inadvertently leak into the C ABI. */
+#include "art_api/dex_file_external.h"
+
+static const char gtest_output_arg[] = "--gtest_output=xml:";
+static const char gtest_output_xml[] = "\
+<?xml version=\"1.0\"?>\n\
+<testsuites tests=\"0\" failures=\"0\" disabled=\"0\" errors=\"0\" name=\"AllTests\">";
+
+/* Writes a dummy gtest xml report to the given path. */
+static int write_gtest_output_xml(char* gtest_output_path) {
+  FILE* output_fd = fopen(gtest_output_path, "w");
+  if (output_fd == NULL) {
+    fprintf(stderr, "Failed to open %s: %s\n", gtest_output_path, strerror(errno));
+    return 1;
+  }
+  if (fprintf(output_fd, gtest_output_xml) != sizeof(gtest_output_xml) - 1) {
+    fprintf(stderr, "Failed to write %s: %s\n", gtest_output_path, strerror(errno));
+    fclose(output_fd);
+    return 1;
+  }
+  if (fclose(output_fd) != 0) {
+    fprintf(stderr, "Failed to close %s: %s\n", gtest_output_path, strerror(errno));
+    return 1;
+  }
+  return 0;
+}
+
+int main(int argc, char** argv) {
+  if (argc >= 2 && strncmp(argv[1], gtest_output_arg, sizeof(gtest_output_arg) - 1) == 0) {
+    /* The ART gtest framework expects all tests to understand --gtest_output. */
+    return write_gtest_output_xml(argv[1] + sizeof(gtest_output_arg) - 1);
+  }
+  return 0;
+}
diff --git a/libdexfile/external/dex_file_supp.cc b/libdexfile/external/dex_file_supp.cc
index 6514c8a..5bd25fc 100644
--- a/libdexfile/external/dex_file_supp.cc
+++ b/libdexfile/external/dex_file_supp.cc
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "art_api/ext_dex_file.h"
+#include "art_api/dex_file_support.h"
 
 namespace art_api {
 namespace dex {
diff --git a/libdexfile/external/dex_file_supp_test.cc b/libdexfile/external/dex_file_supp_test.cc
new file mode 100644
index 0000000..2f7ad50
--- /dev/null
+++ b/libdexfile/external/dex_file_supp_test.cc
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2019 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 <sys/types.h>
+
+#include <memory>
+#include <string>
+#include <string_view>
+
+#include <android-base/file.h>
+#include <dex/dex_file.h>
+#include <gtest/gtest.h>
+
+#include "art_api/dex_file_support.h"
+
+namespace art_api {
+namespace dex {
+
+static constexpr uint32_t kDexData[] = {
+    0x0a786564, 0x00383330, 0xc98b3ab8, 0xf3749d94, 0xaecca4d8, 0xffc7b09a, 0xdca9ca7f, 0x5be5deab,
+    0x00000220, 0x00000070, 0x12345678, 0x00000000, 0x00000000, 0x0000018c, 0x00000008, 0x00000070,
+    0x00000004, 0x00000090, 0x00000002, 0x000000a0, 0x00000000, 0x00000000, 0x00000003, 0x000000b8,
+    0x00000001, 0x000000d0, 0x00000130, 0x000000f0, 0x00000122, 0x0000012a, 0x00000132, 0x00000146,
+    0x00000151, 0x00000154, 0x00000158, 0x0000016d, 0x00000001, 0x00000002, 0x00000004, 0x00000006,
+    0x00000004, 0x00000002, 0x00000000, 0x00000005, 0x00000002, 0x0000011c, 0x00000000, 0x00000000,
+    0x00010000, 0x00000007, 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000,
+    0x00000003, 0x00000000, 0x0000017e, 0x00000000, 0x00010001, 0x00000001, 0x00000173, 0x00000004,
+    0x00021070, 0x000e0000, 0x00010001, 0x00000000, 0x00000178, 0x00000001, 0x0000000e, 0x00000001,
+    0x3c060003, 0x74696e69, 0x4c06003e, 0x6e69614d, 0x4c12003b, 0x6176616a, 0x6e616c2f, 0x624f2f67,
+    0x7463656a, 0x4d09003b, 0x2e6e6961, 0x6176616a, 0x00560100, 0x004c5602, 0x6a4c5b13, 0x2f617661,
+    0x676e616c, 0x7274532f, 0x3b676e69, 0x616d0400, 0x01006e69, 0x000e0700, 0x07000103, 0x0000000e,
+    0x81000002, 0x01f00480, 0x02880901, 0x0000000c, 0x00000000, 0x00000001, 0x00000000, 0x00000001,
+    0x00000008, 0x00000070, 0x00000002, 0x00000004, 0x00000090, 0x00000003, 0x00000002, 0x000000a0,
+    0x00000005, 0x00000003, 0x000000b8, 0x00000006, 0x00000001, 0x000000d0, 0x00002001, 0x00000002,
+    0x000000f0, 0x00001001, 0x00000001, 0x0000011c, 0x00002002, 0x00000008, 0x00000122, 0x00002003,
+    0x00000002, 0x00000173, 0x00002000, 0x00000001, 0x0000017e, 0x00001000, 0x00000001, 0x0000018c,
+};
+
+TEST(DexStringTest, alloc_string) {
+  auto s = DexString("123");
+  EXPECT_EQ(std::string_view(s), "123");
+}
+
+TEST(DexStringTest, alloc_empty_string) {
+  auto s = DexString("");
+  EXPECT_TRUE(std::string_view(s).empty());
+}
+
+TEST(DexStringTest, move_construct) {
+  auto s1 = DexString("foo");
+  auto s2 = DexString(std::move(s1));
+  EXPECT_TRUE(std::string_view(s1).empty());
+  EXPECT_EQ(std::string_view(s2), "foo");
+}
+
+TEST(DexStringTest, move_assign) {
+  auto s1 = DexString("foo");
+  DexString s2;
+  EXPECT_TRUE(std::string_view(s2).empty());
+  s2 = std::move(s1);
+  EXPECT_TRUE(std::string_view(s1).empty());
+  EXPECT_EQ(std::string_view(s2), "foo");
+}
+
+TEST(DexStringTest, reassign) {
+  auto s = DexString("foo");
+  s = DexString("bar");
+  EXPECT_EQ(std::string_view(s), "bar");
+}
+
+TEST(DexStringTest, data_access) {
+  auto s = DexString("foo");
+  EXPECT_STREQ(s.data(), "foo");
+  EXPECT_STREQ(s.c_str(), "foo");
+}
+
+TEST(DexStringTest, size_access) {
+  auto s = DexString("foo");
+  EXPECT_EQ(s.size(), size_t{3});
+  EXPECT_EQ(s.length(), size_t{3});
+}
+
+TEST(DexStringTest, equality) {
+  auto s = DexString("foo");
+  EXPECT_EQ(s, DexString("foo"));
+  EXPECT_FALSE(s == DexString("bar"));
+}
+
+TEST(DexStringTest, equality_with_nul) {
+  auto s = DexString(std::string("foo\0bar", 7));
+  EXPECT_EQ(s.size(), size_t{7});
+  EXPECT_EQ(s, DexString(std::string("foo\0bar", 7)));
+  EXPECT_FALSE(s == DexString(std::string("foo\0baz", 7)));
+}
+
+TEST(DexFileTest, from_memory_header_too_small) {
+  size_t size = sizeof(art::DexFile::Header) - 1;
+  std::string error_msg;
+  EXPECT_EQ(DexFile::OpenFromMemory(kDexData, &size, "", &error_msg), nullptr);
+  EXPECT_EQ(size, sizeof(art::DexFile::Header));
+  EXPECT_TRUE(error_msg.empty());
+}
+
+TEST(DexFileTest, from_memory_file_too_small) {
+  size_t size = sizeof(art::DexFile::Header);
+  std::string error_msg;
+  EXPECT_EQ(DexFile::OpenFromMemory(kDexData, &size, "", &error_msg), nullptr);
+  EXPECT_EQ(size, sizeof(kDexData));
+  EXPECT_TRUE(error_msg.empty());
+}
+
+static std::unique_ptr<DexFile> GetTestDexData() {
+  size_t size = sizeof(kDexData);
+  std::string error_msg;
+  std::unique_ptr<DexFile> dex_file = DexFile::OpenFromMemory(kDexData, &size, "", &error_msg);
+  EXPECT_TRUE(error_msg.empty());
+  return dex_file;
+}
+
+TEST(DexFileTest, from_memory) {
+  EXPECT_NE(GetTestDexData(), nullptr);
+}
+
+TEST(DexFileTest, from_fd_header_too_small) {
+  TemporaryFile tf;
+  ASSERT_NE(tf.fd, -1);
+  ASSERT_EQ(sizeof(art::DexFile::Header) - 1,
+            static_cast<size_t>(
+                TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(art::DexFile::Header) - 1))));
+
+  std::string error_msg;
+  EXPECT_EQ(DexFile::OpenFromFd(tf.fd, 0, tf.path, &error_msg), nullptr);
+  EXPECT_FALSE(error_msg.empty());
+}
+
+TEST(DexFileTest, from_fd_file_too_small) {
+  TemporaryFile tf;
+  ASSERT_NE(tf.fd, -1);
+  ASSERT_EQ(sizeof(art::DexFile::Header),
+            static_cast<size_t>(
+                TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(art::DexFile::Header)))));
+
+  std::string error_msg;
+  EXPECT_EQ(DexFile::OpenFromFd(tf.fd, 0, tf.path, &error_msg), nullptr);
+  EXPECT_FALSE(error_msg.empty());
+}
+
+TEST(DexFileTest, from_fd) {
+  TemporaryFile tf;
+  ASSERT_NE(tf.fd, -1);
+  ASSERT_EQ(sizeof(kDexData),
+            static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
+
+  std::string error_msg;
+  EXPECT_NE(DexFile::OpenFromFd(tf.fd, 0, tf.path, &error_msg), nullptr);
+  EXPECT_TRUE(error_msg.empty());
+}
+
+TEST(DexFileTest, from_fd_non_zero_offset) {
+  TemporaryFile tf;
+  ASSERT_NE(tf.fd, -1);
+  ASSERT_EQ(0x100, lseek(tf.fd, 0x100, SEEK_SET));
+  ASSERT_EQ(sizeof(kDexData),
+            static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
+
+  std::string error_msg;
+  EXPECT_NE(DexFile::OpenFromFd(tf.fd, 0x100, tf.path, &error_msg), nullptr);
+  EXPECT_TRUE(error_msg.empty());
+}
+
+TEST(DexFileTest, get_method_info_for_offset_without_signature) {
+  std::unique_ptr<DexFile> dex_file = GetTestDexData();
+  ASSERT_NE(dex_file, nullptr);
+
+  MethodInfo info = dex_file->GetMethodInfoForOffset(0x102, false);
+  EXPECT_EQ(info.offset, int32_t{0x100});
+  EXPECT_EQ(info.len, int32_t{8});
+  EXPECT_STREQ(info.name.data(), "Main.<init>");
+
+  info = dex_file->GetMethodInfoForOffset(0x118, false);
+  EXPECT_EQ(info.offset, int32_t{0x118});
+  EXPECT_EQ(info.len, int32_t{2});
+  EXPECT_STREQ(info.name.data(), "Main.main");
+
+  // Retrieve a cached result.
+  info = dex_file->GetMethodInfoForOffset(0x104, false);
+  EXPECT_EQ(info.offset, int32_t{0x100});
+  EXPECT_EQ(info.len, int32_t{8});
+  EXPECT_STREQ(info.name.data(), "Main.<init>");
+}
+
+TEST(DexFileTest, get_method_info_for_offset_with_signature) {
+  std::unique_ptr<DexFile> dex_file = GetTestDexData();
+  ASSERT_NE(dex_file, nullptr);
+
+  MethodInfo info = dex_file->GetMethodInfoForOffset(0x102, true);
+  EXPECT_EQ(info.offset, int32_t{0x100});
+  EXPECT_EQ(info.len, int32_t{8});
+  EXPECT_STREQ(info.name.data(), "void Main.<init>()");
+
+  info = dex_file->GetMethodInfoForOffset(0x118, true);
+  EXPECT_EQ(info.offset, int32_t{0x118});
+  EXPECT_EQ(info.len, int32_t{2});
+  EXPECT_STREQ(info.name.data(), "void Main.main(java.lang.String[])");
+
+  // Retrieve a cached result.
+  info = dex_file->GetMethodInfoForOffset(0x104, true);
+  EXPECT_EQ(info.offset, int32_t{0x100});
+  EXPECT_EQ(info.len, int32_t{8});
+  EXPECT_STREQ(info.name.data(), "void Main.<init>()");
+
+  // with_signature doesn't affect the cache.
+  info = dex_file->GetMethodInfoForOffset(0x104, false);
+  EXPECT_EQ(info.offset, int32_t{0x100});
+  EXPECT_EQ(info.len, int32_t{8});
+  EXPECT_STREQ(info.name.data(), "Main.<init>");
+}
+
+TEST(DexFileTest, get_method_info_for_offset_boundaries) {
+  std::unique_ptr<DexFile> dex_file = GetTestDexData();
+  ASSERT_NE(dex_file, nullptr);
+
+  MethodInfo info = dex_file->GetMethodInfoForOffset(0x100000, false);
+  EXPECT_EQ(info.offset, int32_t{0});
+
+  info = dex_file->GetMethodInfoForOffset(0x99, false);
+  EXPECT_EQ(info.offset, int32_t{0});
+  info = dex_file->GetMethodInfoForOffset(0x100, false);
+  EXPECT_EQ(info.offset, int32_t{0x100});
+  info = dex_file->GetMethodInfoForOffset(0x107, false);
+  EXPECT_EQ(info.offset, int32_t{0x100});
+  info = dex_file->GetMethodInfoForOffset(0x108, false);
+  EXPECT_EQ(info.offset, int32_t{0});
+
+  // Make sure that once the whole dex file has been cached, no problems occur.
+  info = dex_file->GetMethodInfoForOffset(0x98, false);
+  EXPECT_EQ(info.offset, int32_t{0});
+
+  // Choose a value that is in the cached map, but not in a valid method.
+  info = dex_file->GetMethodInfoForOffset(0x110, false);
+  EXPECT_EQ(info.offset, int32_t{0});
+}
+
+TEST(DexFileTest, get_all_method_infos_without_signature) {
+  std::unique_ptr<DexFile> dex_file = GetTestDexData();
+  ASSERT_NE(dex_file, nullptr);
+
+  std::vector<MethodInfo> infos;
+  infos.emplace_back(MethodInfo{0x100, 8, DexString("Main.<init>")});
+  infos.emplace_back(MethodInfo{0x118, 2, DexString("Main.main")});
+  ASSERT_EQ(dex_file->GetAllMethodInfos(false), infos);
+}
+
+TEST(DexFileTest, get_all_method_infos_with_signature) {
+  std::unique_ptr<DexFile> dex_file = GetTestDexData();
+  ASSERT_NE(dex_file, nullptr);
+
+  std::vector<MethodInfo> infos;
+  infos.emplace_back(MethodInfo{0x100, 8, DexString("void Main.<init>()")});
+  infos.emplace_back(MethodInfo{0x118, 2, DexString("void Main.main(java.lang.String[])")});
+  ASSERT_EQ(dex_file->GetAllMethodInfos(true), infos);
+}
+
+TEST(DexFileTest, move_construct) {
+  std::unique_ptr<DexFile> dex_file = GetTestDexData();
+  ASSERT_NE(dex_file, nullptr);
+
+  auto df1 = DexFile(std::move(*dex_file));
+  auto df2 = DexFile(std::move(df1));
+
+  MethodInfo info = df2.GetMethodInfoForOffset(0x100, false);
+  EXPECT_EQ(info.offset, int32_t{0x100});
+}
+
+}  // namespace dex
+}  // namespace art_api
diff --git a/libdexfile/external/include/art_api/dex_file_external.h b/libdexfile/external/include/art_api/dex_file_external.h
new file mode 100644
index 0000000..b29e759
--- /dev/null
+++ b/libdexfile/external/include/art_api/dex_file_external.h
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+#ifndef ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_DEX_FILE_EXTERNAL_H_
+#define ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_DEX_FILE_EXTERNAL_H_
+
+// Dex file external API
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// This is the stable C ABI that backs art_api::dex below. Structs and functions
+// may only be added here. C++ users should use dex_file_support.h instead.
+
+// Opaque wrapper for an std::string allocated in libdexfile which must be freed
+// using ExtDexFileFreeString.
+struct ExtDexFileString;
+
+// Returns an ExtDexFileString initialized to the given string.
+const struct ExtDexFileString* ExtDexFileMakeString(const char* str, size_t size);
+
+// Returns a pointer to the underlying null-terminated character array and its
+// size for the given ExtDexFileString.
+const char* ExtDexFileGetString(const struct ExtDexFileString* ext_string, /*out*/ size_t* size);
+
+// Frees an ExtDexFileString.
+void ExtDexFileFreeString(const struct ExtDexFileString* ext_string);
+
+struct ExtDexFileMethodInfo {
+  int32_t offset;
+  int32_t len;
+  const struct ExtDexFileString* name;
+};
+
+struct ExtDexFile;
+
+// See art_api::dex::DexFile::OpenFromMemory. Returns true on success.
+int ExtDexFileOpenFromMemory(const void* addr,
+                             /*inout*/ size_t* size,
+                             const char* location,
+                             /*out*/ const struct ExtDexFileString** error_msg,
+                             /*out*/ struct ExtDexFile** ext_dex_file);
+
+// See art_api::dex::DexFile::OpenFromFd. Returns true on success.
+int ExtDexFileOpenFromFd(int fd,
+                         off_t offset,
+                         const char* location,
+                         /*out*/ const struct ExtDexFileString** error_msg,
+                         /*out*/ struct ExtDexFile** ext_dex_file);
+
+// See art_api::dex::DexFile::GetMethodInfoForOffset. Returns true on success.
+int ExtDexFileGetMethodInfoForOffset(struct ExtDexFile* ext_dex_file,
+                                     int64_t dex_offset,
+                                     int with_signature,
+                                     /*out*/ struct ExtDexFileMethodInfo* method_info);
+
+typedef void ExtDexFileMethodInfoCallback(const struct ExtDexFileMethodInfo* ext_method_info,
+                                          void* user_data);
+
+// See art_api::dex::DexFile::GetAllMethodInfos.
+void ExtDexFileGetAllMethodInfos(struct ExtDexFile* ext_dex_file,
+                                 int with_signature,
+                                 ExtDexFileMethodInfoCallback* method_info_cb,
+                                 void* user_data);
+
+// Frees an ExtDexFile.
+void ExtDexFileFree(struct ExtDexFile* ext_dex_file);
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_DEX_FILE_EXTERNAL_H_
diff --git a/libdexfile/external/include/art_api/ext_dex_file.h b/libdexfile/external/include/art_api/dex_file_support.h
similarity index 62%
rename from libdexfile/external/include/art_api/ext_dex_file.h
rename to libdexfile/external/include/art_api/dex_file_support.h
index 4a52a2b..24222af 100644
--- a/libdexfile/external/include/art_api/ext_dex_file.h
+++ b/libdexfile/external/include/art_api/dex_file_support.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2019 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.
@@ -14,83 +14,21 @@
  * limitations under the License.
  */
 
-#ifndef ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_EXT_DEX_FILE_H_
-#define ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_EXT_DEX_FILE_H_
+#ifndef ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_DEX_FILE_SUPPORT_H_
+#define ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_DEX_FILE_SUPPORT_H_
 
-// Dex file external API
-
-#include <sys/types.h>
+// C++ wrapper for the dex file external API.
 
 #include <cstring>
 #include <memory>
 #include <string>
 #include <string_view>
+#include <utility>
 #include <vector>
 
 #include <android-base/macros.h>
 
-extern "C" {
-
-// This is the stable C ABI that backs art_api::dex below. Structs and functions
-// may only be added here.
-// TODO(b/120978655): Move this to a separate pure C header.
-//
-// Clients should use the C++ wrappers in art_api::dex instead.
-
-// Opaque wrapper for an std::string allocated in libdexfile which must be freed
-// using ExtDexFileFreeString.
-class ExtDexFileString;
-
-// Returns an ExtDexFileString initialized to the given string.
-const ExtDexFileString* ExtDexFileMakeString(const char* str);
-
-// Returns a pointer to the underlying null-terminated character array and its
-// size for the given ExtDexFileString.
-const char* ExtDexFileGetString(const ExtDexFileString* ext_string, /*out*/ size_t* size);
-
-// Frees an ExtDexFileString.
-void ExtDexFileFreeString(const ExtDexFileString* ext_string);
-
-struct ExtDexFileMethodInfo {
-  int32_t offset;
-  int32_t len;
-  const ExtDexFileString* name;
-};
-
-class ExtDexFile;
-
-// See art_api::dex::DexFile::OpenFromMemory. Returns true on success.
-int ExtDexFileOpenFromMemory(const void* addr,
-                             /*inout*/ size_t* size,
-                             const char* location,
-                             /*out*/ const ExtDexFileString** error_msg,
-                             /*out*/ ExtDexFile** ext_dex_file);
-
-// See art_api::dex::DexFile::OpenFromFd. Returns true on success.
-int ExtDexFileOpenFromFd(int fd,
-                         off_t offset,
-                         const char* location,
-                         /*out*/ const ExtDexFileString** error_msg,
-                         /*out*/ ExtDexFile** ext_dex_file);
-
-// See art_api::dex::DexFile::GetMethodInfoForOffset. Returns true on success.
-int ExtDexFileGetMethodInfoForOffset(ExtDexFile* ext_dex_file,
-                                     int64_t dex_offset,
-                                     /*out*/ ExtDexFileMethodInfo* method_info);
-
-typedef void ExtDexFileMethodInfoCallback(const ExtDexFileMethodInfo* ext_method_info,
-                                          void* user_data);
-
-// See art_api::dex::DexFile::GetAllMethodInfos.
-void ExtDexFileGetAllMethodInfos(ExtDexFile* ext_dex_file,
-                                 int with_signature,
-                                 ExtDexFileMethodInfoCallback* method_info_cb,
-                                 void* user_data);
-
-// Frees an ExtDexFile.
-void ExtDexFileFree(ExtDexFile* ext_dex_file);
-
-}  // extern "C"
+#include "art_api/dex_file_external.h"
 
 namespace art_api {
 namespace dex {
@@ -98,12 +36,17 @@
 // Minimal std::string look-alike for a string returned from libdexfile.
 class DexString final {
  public:
-  DexString(DexString&& dex_str) noexcept { ReplaceExtString(std::move(dex_str)); }
-  explicit DexString(const char* str = "") : ext_string_(ExtDexFileMakeString(str)) {}
+  DexString(DexString&& dex_str) noexcept : ext_string_(dex_str.ext_string_) {
+    dex_str.ext_string_ = ExtDexFileMakeString("", 0);
+  }
+  explicit DexString(const char* str = "")
+      : ext_string_(ExtDexFileMakeString(str, std::strlen(str))) {}
+  explicit DexString(std::string_view str)
+      : ext_string_(ExtDexFileMakeString(str.data(), str.size())) {}
   ~DexString() { ExtDexFileFreeString(ext_string_); }
 
   DexString& operator=(DexString&& dex_str) noexcept {
-    ReplaceExtString(std::move(dex_str));
+    std::swap(ext_string_, dex_str.ext_string_);
     return *this;
   }
 
@@ -132,11 +75,6 @@
   explicit DexString(const ExtDexFileString* ext_string) : ext_string_(ext_string) {}
   const ExtDexFileString* ext_string_;  // Owned instance. Never nullptr.
 
-  void ReplaceExtString(DexString&& dex_str) {
-    ext_string_ = dex_str.ext_string_;
-    dex_str.ext_string_ = ExtDexFileMakeString("");
-  }
-
   DISALLOW_COPY_AND_ASSIGN(DexString);
 };
 
@@ -211,10 +149,15 @@
 
   // Given an offset relative to the start of the dex file header, if there is a
   // method whose instruction range includes that offset then returns info about
-  // it, otherwise returns a struct with offset == 0.
-  MethodInfo GetMethodInfoForOffset(int64_t dex_offset) {
+  // it, otherwise returns a struct with offset == 0. MethodInfo.name receives
+  // the full function signature if with_signature is set, otherwise it gets the
+  // class and method name only.
+  MethodInfo GetMethodInfoForOffset(int64_t dex_offset, bool with_signature) {
     ExtDexFileMethodInfo ext_method_info;
-    if (ExtDexFileGetMethodInfoForOffset(ext_dex_file_, dex_offset, &ext_method_info)) {
+    if (ExtDexFileGetMethodInfoForOffset(ext_dex_file_,
+                                         dex_offset,
+                                         with_signature,
+                                         &ext_method_info)) {
       return AbsorbMethodInfo(ext_method_info);
     }
     return {/*offset=*/0, /*len=*/0, /*name=*/DexString()};
@@ -223,10 +166,12 @@
   // Returns info structs about all methods in the dex file. MethodInfo.name
   // receives the full function signature if with_signature is set, otherwise it
   // gets the class and method name only.
-  std::vector<MethodInfo> GetAllMethodInfos(bool with_signature = true) {
+  std::vector<MethodInfo> GetAllMethodInfos(bool with_signature) {
     MethodInfoVector res;
-    ExtDexFileGetAllMethodInfos(
-        ext_dex_file_, with_signature, AddMethodInfoCallback, static_cast<void*>(&res));
+    ExtDexFileGetAllMethodInfos(ext_dex_file_,
+                                with_signature,
+                                AddMethodInfoCallback,
+                                static_cast<void*>(&res));
     return res;
   }
 
@@ -245,4 +190,4 @@
 }  // namespace dex
 }  // namespace art_api
 
-#endif  // ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_EXT_DEX_FILE_H_
+#endif  // ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_DEX_FILE_SUPPORT_H_
diff --git a/libprofile/Android.bp b/libprofile/Android.bp
index a8d8b2f..fd32c5f 100644
--- a/libprofile/Android.bp
+++ b/libprofile/Android.bp
@@ -23,33 +23,55 @@
     ],
     target: {
         android: {
+            shared_libs: [
+                "libartbase",
+                "libdexfile",
+                "libartbase",
+	        // For atrace.
+                "libcutils",
+                "libbase",
+            ],
             static_libs: [
                 // ZipArchive support, the order matters here to get all symbols.
                 "libziparchive",
                 "libz",
             ],
+            export_shared_lib_headers: ["libbase"],
         },
-        host: {
+        not_windows: {
             shared_libs: [
+                "libartbase",
+                "libdexfile",
+                "libartbase",
+	        // For atrace.
+                "libcutils",
                 "libziparchive",
                 "libz",
+                "libbase",
             ],
+            export_shared_lib_headers: ["libbase"],
+        },
+        windows: {
+	    cflags: ["-Wno-thread-safety"],
+            static_libs: [
+                "libartbase",
+                "libdexfile",
+                "libartbase",
+	        // For atrace.
+                "libcutils",
+                "libziparchive",
+                "libz",
+                "libbase",
+            ],
+            export_static_lib_headers: ["libbase"],
         },
     },
     //generated_sources: ["art_libartbase_operator_srcs"],
     cflags: ["-DBUILDING_LIBART=1"],
-    shared_libs: [
-        "libartbase",
-        "libdexfile",
-        "libartbase",
-	// For atrace.
-        "libcutils",
-    ],
     export_include_dirs: ["."],
     // ART's macros.h depends on libbase's macros.h.
     // Note: runtime_options.h depends on cmdline. But we don't really want to export this
     //       generically. dex2oat takes care of it itself.
-    export_shared_lib_headers: ["libbase"],
 }
 
 cc_defaults {
@@ -95,6 +117,14 @@
         "libziparchive",
     ],
     export_shared_lib_headers: ["libbase"],
+    target: {
+        windows: {
+	    enabled: true,
+	    shared: {
+	        enabled: false,
+	    },
+	},
+    }
 }
 
 art_cc_library {
diff --git a/libprofile/profile/profile_compilation_info.cc b/libprofile/profile/profile_compilation_info.cc
index 8b8569d..47b17ae 100644
--- a/libprofile/profile/profile_compilation_info.cc
+++ b/libprofile/profile/profile_compilation_info.cc
@@ -19,7 +19,6 @@
 #include <sys/file.h>
 #include <sys/stat.h>
 #include <sys/types.h>
-#include <sys/uio.h>
 #include <unistd.h>
 #include <zlib.h>
 
@@ -208,7 +207,11 @@
 
 bool ProfileCompilationInfo::MergeWith(const std::string& filename) {
   std::string error;
+#ifdef _WIN32
+  int flags = O_RDONLY;
+#else
   int flags = O_RDONLY | O_NOFOLLOW | O_CLOEXEC;
+#endif
   ScopedFlock profile_file =
       LockedFile::Open(filename.c_str(), flags, /*block=*/false, &error);
 
@@ -236,7 +239,11 @@
     return kProfileLoadWouldOverwiteData;
   }
 
+#ifdef _WIN32
+  int flags = O_RDWR;
+#else
   int flags = O_RDWR | O_NOFOLLOW | O_CLOEXEC;
+#endif
   // There's no need to fsync profile data right away. We get many chances
   // to write it again in case something goes wrong. We can rely on a simple
   // close(), no sync, and let to the kernel decide when to write to disk.
@@ -274,7 +281,11 @@
 bool ProfileCompilationInfo::Save(const std::string& filename, uint64_t* bytes_written) {
   ScopedTrace trace(__PRETTY_FUNCTION__);
   std::string error;
+#ifdef _WIN32
+  int flags = O_WRONLY;
+#else
   int flags = O_WRONLY | O_NOFOLLOW | O_CLOEXEC;
+#endif
   // There's no need to fsync profile data right away. We get many chances
   // to write it again in case something goes wrong. We can rely on a simple
   // close(), no sync, and let to the kernel decide when to write to disk.
diff --git a/openjdkjvmti/OpenjdkJvmTi.cc b/openjdkjvmti/OpenjdkJvmTi.cc
index bd5b598..7a2b638 100644
--- a/openjdkjvmti/OpenjdkJvmTi.cc
+++ b/openjdkjvmti/OpenjdkJvmTi.cc
@@ -1552,7 +1552,7 @@
 
   {
     // Make sure we can deopt anything we need to.
-    art::ScopedObjectAccess soa(art::Thread::Current());
+    art::ScopedSuspendAll ssa(__FUNCTION__);
     gDeoptManager->FinishSetup();
   }
 
diff --git a/openjdkjvmti/deopt_manager.h b/openjdkjvmti/deopt_manager.h
index d9f34a5..065baa7 100644
--- a/openjdkjvmti/deopt_manager.h
+++ b/openjdkjvmti/deopt_manager.h
@@ -107,7 +107,7 @@
 
   void FinishSetup()
       REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_)
-      REQUIRES_SHARED(art::Locks::mutator_lock_);
+      REQUIRES(art::Locks::mutator_lock_);
 
   static DeoptManager* Get();
 
diff --git a/openjdkjvmti/events.cc b/openjdkjvmti/events.cc
index 7fb6a15..22c622a 100644
--- a/openjdkjvmti/events.cc
+++ b/openjdkjvmti/events.cc
@@ -34,6 +34,7 @@
 #include <array>
 #include <sys/time.h>
 
+#include "arch/context.h"
 #include "art_field-inl.h"
 #include "art_jvmti.h"
 #include "art_method-inl.h"
diff --git a/openjdkjvmti/ti_method.cc b/openjdkjvmti/ti_method.cc
index 7d69c89..e88539f 100644
--- a/openjdkjvmti/ti_method.cc
+++ b/openjdkjvmti/ti_method.cc
@@ -33,6 +33,7 @@
 
 #include <type_traits>
 
+#include "arch/context.h"
 #include "art_jvmti.h"
 #include "art_method-inl.h"
 #include "base/enums.h"
diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc
index 4bcb7b2..3d175a8 100644
--- a/openjdkjvmti/ti_redefine.cc
+++ b/openjdkjvmti/ti_redefine.cc
@@ -188,7 +188,9 @@
     if (obsoleted_methods_.find(old_method) != obsoleted_methods_.end()) {
       // We cannot ensure that the right dex file is used in inlined frames so we don't support
       // redefining them.
-      DCHECK(!IsInInlinedFrame()) << "Inlined frames are not supported when using redefinition";
+      DCHECK(!IsInInlinedFrame()) << "Inlined frames are not supported when using redefinition: "
+                                  << old_method->PrettyMethod() << " is inlined into "
+                                  << GetOuterMethod()->PrettyMethod();
       art::ArtMethod* new_obsolete_method = obsolete_maps_->FindObsoleteVersion(old_method);
       if (new_obsolete_method == nullptr) {
         // Create a new Obsolete Method and put it in the list.
diff --git a/openjdkjvmti/ti_stack.cc b/openjdkjvmti/ti_stack.cc
index 4a3eac8..385ac45 100644
--- a/openjdkjvmti/ti_stack.cc
+++ b/openjdkjvmti/ti_stack.cc
@@ -36,6 +36,7 @@
 #include <unordered_map>
 #include <vector>
 
+#include "arch/context.h"
 #include "art_field-inl.h"
 #include "art_method-inl.h"
 #include "art_jvmti.h"
diff --git a/profman/Android.bp b/profman/Android.bp
index 89e1f7e..33cca02 100644
--- a/profman/Android.bp
+++ b/profman/Android.bp
@@ -40,7 +40,6 @@
     name: "profman",
     defaults: ["profman-defaults"],
     shared_libs: [
-        "libart",
         "libprofile",
         "libdexfile",
         "libartbase",
@@ -54,13 +53,33 @@
         "profman-defaults",
     ],
     shared_libs: [
-        "libartd",
         "libprofiled",
         "libdexfiled",
         "libartbased",
     ],
 }
 
+art_cc_binary {
+    name: "profmans",
+    defaults: [
+        "profman-defaults",
+        "libprofile_static_defaults",
+        "libdexfile_static_defaults",
+        "libartbase_static_defaults",
+    ],
+    host_supported: true,
+    device_supported: false,
+    target: {
+        darwin: {
+            enabled: false,
+        },
+        windows: {
+            enabled: true,
+	    cflags: ["-Wno-thread-safety"],
+        },
+    },
+}
+
 art_cc_test {
     name: "art_profman_tests",
     defaults: [
diff --git a/profman/profman.cc b/profman/profman.cc
index 88c5c4e..82d9df0 100644
--- a/profman/profman.cc
+++ b/profman/profman.cc
@@ -467,6 +467,10 @@
   // The methods reads the links from /proc/self/fd/ to find the original apk paths
   // and puts them in the dex_locations_ vector.
   bool ComputeDexLocationsFromApkFds() {
+#ifdef _WIN32
+    PLOG(ERROR) << "ComputeDexLocationsFromApkFds is unsupported on Windows.";
+    return false;
+#else
     // We can't use a char array of PATH_MAX size without exceeding the frame size.
     // So we use a vector as the buffer for the path.
     std::vector<char> buffer(PATH_MAX, 0);
@@ -482,11 +486,17 @@
       dex_locations_.push_back(buffer.data());
     }
     return true;
+#endif
   }
 
   std::unique_ptr<const ProfileCompilationInfo> LoadProfile(const std::string& filename, int fd) {
     if (!filename.empty()) {
-      fd = open(filename.c_str(), O_RDWR | O_CLOEXEC);
+#ifdef _WIN32
+      int flags = O_RDWR;
+#else
+      int flags = O_RDWR | O_CLOEXEC;
+#endif
+      fd = open(filename.c_str(), flags);
       if (fd < 0) {
         LOG(ERROR) << "Cannot open " << filename << strerror(errno);
         return nullptr;
@@ -650,7 +660,12 @@
   bool GetClassNamesAndMethods(const std::string& profile_file,
                                std::vector<std::unique_ptr<const DexFile>>* dex_files,
                                std::set<std::string>* out_lines) {
-    int fd = open(profile_file.c_str(), O_RDONLY | O_CLOEXEC);
+#ifdef _WIN32
+    int flags = O_RDONLY;
+#else
+    int flags = O_RDONLY | O_CLOEXEC;
+#endif
+    int fd = open(profile_file.c_str(), flags);
     if (!FdIsValid(fd)) {
       LOG(ERROR) << "Cannot open " << profile_file << strerror(errno);
       return false;
@@ -1031,7 +1046,12 @@
     int fd = reference_profile_file_fd_;
     if (!FdIsValid(fd)) {
       CHECK(!reference_profile_file_.empty());
-      fd = open(reference_profile_file_.c_str(), O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC, 0644);
+#ifdef _WIN32
+      int flags = O_CREAT | O_TRUNC | O_WRONLY;
+#else
+      int flags = O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC;
+#endif
+      fd = open(reference_profile_file_.c_str(), flags, 0644);
       if (fd < 0) {
         LOG(ERROR) << "Cannot open " << reference_profile_file_ << strerror(errno);
         return kInvalidFd;
@@ -1164,9 +1184,12 @@
       }
     }
     // ShouldGenerateTestProfile confirms !test_profile_.empty().
-    int profile_test_fd = open(test_profile_.c_str(),
-                               O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC,
-                               0644);
+#ifdef _WIN32
+    int flags = O_CREAT | O_TRUNC | O_WRONLY;
+#else
+    int flags = O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC;
+#endif
+    int profile_test_fd = open(test_profile_.c_str(), flags, 0644);
     if (profile_test_fd < 0) {
       LOG(ERROR) << "Cannot open " << test_profile_ << strerror(errno);
       return -1;
diff --git a/runtime/Android.bp b/runtime/Android.bp
index 71c5b74..b89eb02 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -462,6 +462,7 @@
     cmd: "$(location generate_operator_out) art/runtime $(in) > $(out)",
     tools: ["generate_operator_out"],
     srcs: [
+        "base/callee_save_type.h",
         "base/locks.h",
         "class_loader_context.h",
         "class_status.h",
diff --git a/runtime/arch/arm/callee_save_frame_arm.h b/runtime/arch/arm/callee_save_frame_arm.h
index 11eefb9..72ba3b7 100644
--- a/runtime/arch/arm/callee_save_frame_arm.h
+++ b/runtime/arch/arm/callee_save_frame_arm.h
@@ -21,9 +21,9 @@
 #include "base/bit_utils.h"
 #include "base/callee_save_type.h"
 #include "base/enums.h"
-#include "base/globals.h"
 #include "quick/quick_method_frame_info.h"
 #include "registers_arm.h"
+#include "runtime_globals.h"
 
 namespace art {
 namespace arm {
diff --git a/runtime/arch/arm/fault_handler_arm.cc b/runtime/arch/arm/fault_handler_arm.cc
index bb33a27..e186cd3 100644
--- a/runtime/arch/arm/fault_handler_arm.cc
+++ b/runtime/arch/arm/fault_handler_arm.cc
@@ -18,12 +18,13 @@
 
 #include <sys/ucontext.h>
 
+#include "arch/instruction_set.h"
 #include "art_method.h"
 #include "base/enums.h"
-#include "base/globals.h"
 #include "base/hex_dump.h"
 #include "base/logging.h"  // For VLOG.
 #include "base/macros.h"
+#include "runtime_globals.h"
 #include "thread-current-inl.h"
 
 //
diff --git a/runtime/arch/arm64/callee_save_frame_arm64.h b/runtime/arch/arm64/callee_save_frame_arm64.h
index a5aea2a..d3609f1 100644
--- a/runtime/arch/arm64/callee_save_frame_arm64.h
+++ b/runtime/arch/arm64/callee_save_frame_arm64.h
@@ -21,9 +21,9 @@
 #include "base/bit_utils.h"
 #include "base/callee_save_type.h"
 #include "base/enums.h"
-#include "base/globals.h"
 #include "quick/quick_method_frame_info.h"
 #include "registers_arm64.h"
+#include "runtime_globals.h"
 
 namespace art {
 namespace arm64 {
diff --git a/runtime/arch/arm64/fault_handler_arm64.cc b/runtime/arch/arm64/fault_handler_arm64.cc
index e8b4627..751c05b 100644
--- a/runtime/arch/arm64/fault_handler_arm64.cc
+++ b/runtime/arch/arm64/fault_handler_arm64.cc
@@ -18,13 +18,14 @@
 
 #include <sys/ucontext.h>
 
+#include "arch/instruction_set.h"
 #include "art_method.h"
 #include "base/enums.h"
-#include "base/globals.h"
 #include "base/hex_dump.h"
 #include "base/logging.h"  // For VLOG.
 #include "base/macros.h"
 #include "registers_arm64.h"
+#include "runtime_globals.h"
 #include "thread-current-inl.h"
 
 extern "C" void art_quick_throw_stack_overflow();
diff --git a/runtime/arch/instruction_set_features.cc b/runtime/arch/instruction_set_features.cc
index 0c45bc9..886b40a 100644
--- a/runtime/arch/instruction_set_features.cc
+++ b/runtime/arch/instruction_set_features.cc
@@ -16,6 +16,9 @@
 
 #include "instruction_set_features.h"
 
+#include <algorithm>
+#include <ostream>
+
 #include "android-base/strings.h"
 
 #include "base/casts.h"
diff --git a/runtime/arch/instruction_set_features.h b/runtime/arch/instruction_set_features.h
index c31c927..f910a41 100644
--- a/runtime/arch/instruction_set_features.h
+++ b/runtime/arch/instruction_set_features.h
@@ -17,8 +17,8 @@
 #ifndef ART_RUNTIME_ARCH_INSTRUCTION_SET_FEATURES_H_
 #define ART_RUNTIME_ARCH_INSTRUCTION_SET_FEATURES_H_
 
+#include <iosfwd>
 #include <memory>
-#include <ostream>
 #include <vector>
 
 #include "arch/instruction_set.h"
diff --git a/runtime/arch/mips/callee_save_frame_mips.h b/runtime/arch/mips/callee_save_frame_mips.h
index 6e88d08..84ce209 100644
--- a/runtime/arch/mips/callee_save_frame_mips.h
+++ b/runtime/arch/mips/callee_save_frame_mips.h
@@ -21,9 +21,9 @@
 #include "base/bit_utils.h"
 #include "base/callee_save_type.h"
 #include "base/enums.h"
-#include "base/globals.h"
 #include "quick/quick_method_frame_info.h"
 #include "registers_mips.h"
+#include "runtime_globals.h"
 
 namespace art {
 namespace mips {
diff --git a/runtime/arch/mips/fault_handler_mips.cc b/runtime/arch/mips/fault_handler_mips.cc
index 7c8ac28..0354f0c 100644
--- a/runtime/arch/mips/fault_handler_mips.cc
+++ b/runtime/arch/mips/fault_handler_mips.cc
@@ -17,14 +17,15 @@
 #include <sys/ucontext.h>
 #include "fault_handler.h"
 
+#include "arch/instruction_set.h"
 #include "arch/mips/callee_save_frame_mips.h"
 #include "art_method.h"
 #include "base/callee_save_type.h"
-#include "base/globals.h"
 #include "base/hex_dump.h"
 #include "base/logging.h"  // For VLOG.
 #include "base/macros.h"
 #include "registers_mips.h"
+#include "runtime_globals.h"
 #include "thread-current-inl.h"
 
 extern "C" void art_quick_throw_stack_overflow();
diff --git a/runtime/arch/mips/registers_mips.h b/runtime/arch/mips/registers_mips.h
index 34f2f96..4900e41 100644
--- a/runtime/arch/mips/registers_mips.h
+++ b/runtime/arch/mips/registers_mips.h
@@ -19,9 +19,6 @@
 
 #include <iosfwd>
 
-#include <android-base/logging.h>
-
-#include "base/globals.h"
 #include "base/macros.h"
 
 namespace art {
diff --git a/runtime/arch/mips64/callee_save_frame_mips64.h b/runtime/arch/mips64/callee_save_frame_mips64.h
index 59529a0..64d6bec 100644
--- a/runtime/arch/mips64/callee_save_frame_mips64.h
+++ b/runtime/arch/mips64/callee_save_frame_mips64.h
@@ -21,9 +21,9 @@
 #include "base/bit_utils.h"
 #include "base/callee_save_type.h"
 #include "base/enums.h"
-#include "base/globals.h"
 #include "quick/quick_method_frame_info.h"
 #include "registers_mips64.h"
+#include "runtime_globals.h"
 
 namespace art {
 namespace mips64 {
diff --git a/runtime/arch/mips64/fault_handler_mips64.cc b/runtime/arch/mips64/fault_handler_mips64.cc
index 85f3528..6255235 100644
--- a/runtime/arch/mips64/fault_handler_mips64.cc
+++ b/runtime/arch/mips64/fault_handler_mips64.cc
@@ -18,14 +18,15 @@
 
 #include <sys/ucontext.h>
 
+#include "arch/instruction_set.h"
 #include "arch/mips64/callee_save_frame_mips64.h"
 #include "art_method.h"
 #include "base/callee_save_type.h"
-#include "base/globals.h"
 #include "base/hex_dump.h"
 #include "base/logging.h"  // For VLOG.
 #include "base/macros.h"
 #include "registers_mips64.h"
+#include "runtime_globals.h"
 #include "thread-current-inl.h"
 
 extern "C" void art_quick_throw_stack_overflow();
diff --git a/runtime/arch/mips64/registers_mips64.h b/runtime/arch/mips64/registers_mips64.h
index a3fa2ac4..1c22c07 100644
--- a/runtime/arch/mips64/registers_mips64.h
+++ b/runtime/arch/mips64/registers_mips64.h
@@ -19,9 +19,6 @@
 
 #include <iosfwd>
 
-#include <android-base/logging.h>
-
-#include "base/globals.h"
 #include "base/macros.h"
 
 namespace art {
diff --git a/runtime/arch/x86/callee_save_frame_x86.h b/runtime/arch/x86/callee_save_frame_x86.h
index f336f43..2edcade 100644
--- a/runtime/arch/x86/callee_save_frame_x86.h
+++ b/runtime/arch/x86/callee_save_frame_x86.h
@@ -21,9 +21,9 @@
 #include "base/bit_utils.h"
 #include "base/callee_save_type.h"
 #include "base/enums.h"
-#include "base/globals.h"
 #include "quick/quick_method_frame_info.h"
 #include "registers_x86.h"
+#include "runtime_globals.h"
 
 namespace art {
 namespace x86 {
diff --git a/runtime/arch/x86/fault_handler_x86.cc b/runtime/arch/x86/fault_handler_x86.cc
index 8b24334..26312fb 100644
--- a/runtime/arch/x86/fault_handler_x86.cc
+++ b/runtime/arch/x86/fault_handler_x86.cc
@@ -18,13 +18,14 @@
 
 #include <sys/ucontext.h>
 
+#include "arch/instruction_set.h"
 #include "art_method.h"
 #include "base/enums.h"
-#include "base/globals.h"
 #include "base/hex_dump.h"
 #include "base/logging.h"  // For VLOG.
 #include "base/macros.h"
 #include "base/safe_copy.h"
+#include "runtime_globals.h"
 #include "thread-current-inl.h"
 
 #if defined(__APPLE__)
diff --git a/runtime/arch/x86/registers_x86.h b/runtime/arch/x86/registers_x86.h
index d3b959f..ff6c18f 100644
--- a/runtime/arch/x86/registers_x86.h
+++ b/runtime/arch/x86/registers_x86.h
@@ -19,9 +19,6 @@
 
 #include <iosfwd>
 
-#include <android-base/logging.h>
-
-#include "base/globals.h"
 #include "base/macros.h"
 
 namespace art {
diff --git a/runtime/arch/x86_64/callee_save_frame_x86_64.h b/runtime/arch/x86_64/callee_save_frame_x86_64.h
index 228a902..d4f2da7 100644
--- a/runtime/arch/x86_64/callee_save_frame_x86_64.h
+++ b/runtime/arch/x86_64/callee_save_frame_x86_64.h
@@ -21,9 +21,9 @@
 #include "base/bit_utils.h"
 #include "base/callee_save_type.h"
 #include "base/enums.h"
-#include "base/globals.h"
 #include "quick/quick_method_frame_info.h"
 #include "registers_x86_64.h"
+#include "runtime_globals.h"
 
 namespace art {
 namespace x86_64 {
diff --git a/runtime/arch/x86_64/registers_x86_64.h b/runtime/arch/x86_64/registers_x86_64.h
index 66aea70..248c82b 100644
--- a/runtime/arch/x86_64/registers_x86_64.h
+++ b/runtime/arch/x86_64/registers_x86_64.h
@@ -19,9 +19,6 @@
 
 #include <iosfwd>
 
-#include <android-base/logging.h>
-
-#include "base/globals.h"
 #include "base/macros.h"
 
 namespace art {
diff --git a/runtime/art_method.h b/runtime/art_method.h
index aed9f62..aabd093 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -476,7 +476,7 @@
   }
 
   ProfilingInfo* GetProfilingInfo(PointerSize pointer_size) REQUIRES_SHARED(Locks::mutator_lock_) {
-    if (UNLIKELY(IsNative()) || UNLIKELY(IsProxyMethod())) {
+    if (UNLIKELY(IsNative() || IsProxyMethod() || !IsInvokable())) {
       return nullptr;
     }
     return reinterpret_cast<ProfilingInfo*>(GetDataPtrSize(pointer_size));
diff --git a/libartbase/base/callee_save_type.h b/runtime/base/callee_save_type.h
similarity index 89%
rename from libartbase/base/callee_save_type.h
rename to runtime/base/callee_save_type.h
index 3e44a3a..e7cc7e6 100644
--- a/libartbase/base/callee_save_type.h
+++ b/runtime/base/callee_save_type.h
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-#ifndef ART_LIBARTBASE_BASE_CALLEE_SAVE_TYPE_H_
-#define ART_LIBARTBASE_BASE_CALLEE_SAVE_TYPE_H_
+#ifndef ART_RUNTIME_BASE_CALLEE_SAVE_TYPE_H_
+#define ART_RUNTIME_BASE_CALLEE_SAVE_TYPE_H_
 
-#include <cstddef>
-#include <ostream>
+#include <cstdint>
+#include <iosfwd>
 
 namespace art {
 
@@ -44,4 +44,4 @@
 
 }  // namespace art
 
-#endif  // ART_LIBARTBASE_BASE_CALLEE_SAVE_TYPE_H_
+#endif  // ART_RUNTIME_BASE_CALLEE_SAVE_TYPE_H_
diff --git a/runtime/base/mutex.h b/runtime/base/mutex.h
index 41a47af..aaa1ee6 100644
--- a/runtime/base/mutex.h
+++ b/runtime/base/mutex.h
@@ -28,7 +28,7 @@
 
 #include "base/aborting.h"
 #include "base/atomic.h"
-#include "base/globals.h"
+#include "runtime_globals.h"
 #include "base/macros.h"
 #include "locks.h"
 
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 5d1f20c..d29a6b7 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -229,7 +229,9 @@
   }
 }
 
-void ClassLinker::ThrowEarlierClassFailure(ObjPtr<mirror::Class> c, bool wrap_in_no_class_def) {
+void ClassLinker::ThrowEarlierClassFailure(ObjPtr<mirror::Class> c,
+                                           bool wrap_in_no_class_def,
+                                           bool log) {
   // The class failed to initialize on a previous attempt, so we want to throw
   // a NoClassDefFoundError (v2 2.17.5).  The exception to this rule is if we
   // failed in verification, in which case v2 5.4.1 says we need to re-throw
@@ -245,8 +247,10 @@
         extra = verify_error->AsThrowable()->Dump();
       }
     }
-    LOG(INFO) << "Rejecting re-init on previously-failed class " << c->PrettyClass()
-              << ": " << extra;
+    if (log) {
+      LOG(INFO) << "Rejecting re-init on previously-failed class " << c->PrettyClass()
+                << ": " << extra;
+    }
   }
 
   CHECK(c->IsErroneous()) << c->PrettyClass() << " " << c->GetStatus();
@@ -5044,7 +5048,7 @@
 
     // Was the class already found to be erroneous? Done under the lock to match the JLS.
     if (klass->IsErroneous()) {
-      ThrowEarlierClassFailure(klass.Get(), true);
+      ThrowEarlierClassFailure(klass.Get(), true, /* log= */ true);
       VlogClassInitializationFailure(klass);
       return false;
     }
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index b9ac9ca..4f4cb4b 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -17,6 +17,7 @@
 #ifndef ART_RUNTIME_CLASS_LINKER_H_
 #define ART_RUNTIME_CLASS_LINKER_H_
 
+#include <list>
 #include <set>
 #include <string>
 #include <unordered_map>
@@ -89,6 +90,7 @@
 class Runtime;
 class ScopedObjectAccessAlreadyRunnable;
 template<size_t kNumReferences> class PACKED(4) StackHandleScope;
+class Thread;
 
 enum VisitRootFlags : uint8_t;
 
@@ -685,7 +687,9 @@
 
   // Throw the class initialization failure recorded when first trying to initialize the given
   // class.
-  void ThrowEarlierClassFailure(ObjPtr<mirror::Class> c, bool wrap_in_no_class_def = false)
+  void ThrowEarlierClassFailure(ObjPtr<mirror::Class> c,
+                                bool wrap_in_no_class_def = false,
+                                bool log = false)
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Locks::dex_lock_);
 
diff --git a/runtime/common_runtime_test.h b/runtime/common_runtime_test.h
index 29b7813..d7f6127 100644
--- a/runtime/common_runtime_test.h
+++ b/runtime/common_runtime_test.h
@@ -26,7 +26,6 @@
 
 #include "arch/instruction_set.h"
 #include "base/common_art_test.h"
-#include "base/globals.h"
 #include "base/locks.h"
 #include "base/os.h"
 #include "base/unix_file/fd_file.h"
@@ -34,6 +33,7 @@
 #include "dex/compact_dex_level.h"
 // TODO: Add inl file and avoid including inl.
 #include "obj_ptr-inl.h"
+#include "runtime_globals.h"
 #include "scoped_thread_state_change-inl.h"
 
 namespace art {
diff --git a/runtime/compiler_filter.cc b/runtime/compiler_filter.cc
index bda64eb..c086490 100644
--- a/runtime/compiler_filter.cc
+++ b/runtime/compiler_filter.cc
@@ -16,6 +16,8 @@
 
 #include "compiler_filter.h"
 
+#include <ostream>
+
 #include "base/utils.h"
 
 namespace art {
diff --git a/runtime/compiler_filter.h b/runtime/compiler_filter.h
index 012ebcb..c36e40f 100644
--- a/runtime/compiler_filter.h
+++ b/runtime/compiler_filter.h
@@ -17,7 +17,7 @@
 #ifndef ART_RUNTIME_COMPILER_FILTER_H_
 #define ART_RUNTIME_COMPILER_FILTER_H_
 
-#include <ostream>
+#include <iosfwd>
 #include <string>
 #include <vector>
 
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index adf01c3..663af81 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -681,13 +681,13 @@
   //
   // The performance cost of this is non-negligible during native-debugging due to the
   // forced JIT, so we keep the AOT code in that case in exchange for limited native debugging.
+  ScopedSuspendAll ssa(__FUNCTION__);
   if (!runtime->IsJavaDebuggable() &&
       !runtime->GetInstrumentation()->IsForcedInterpretOnly() &&
       !runtime->IsNativeDebuggable()) {
     runtime->DeoptimizeBootImage();
   }
 
-  ScopedSuspendAll ssa(__FUNCTION__);
   if (RequiresDeoptimization()) {
     runtime->GetInstrumentation()->EnableDeoptimization();
   }
diff --git a/runtime/dexopt_test.cc b/runtime/dexopt_test.cc
index 7f697d1..9c0ac8f 100644
--- a/runtime/dexopt_test.cc
+++ b/runtime/dexopt_test.cc
@@ -72,7 +72,8 @@
                                     const std::string& oat_location,
                                     CompilerFilter::Filter filter,
                                     bool with_alternate_image,
-                                    const char* compilation_reason) {
+                                    const char* compilation_reason,
+                                    const std::vector<std::string>& extra_args) {
   std::string dalvik_cache = GetDalvikCache(GetInstructionSetString(kRuntimeISA));
   std::string dalvik_cache_tmp = dalvik_cache + ".redirected";
 
@@ -101,6 +102,8 @@
     args.push_back("--compilation-reason=" + std::string(compilation_reason));
   }
 
+  args.insert(args.end(), extra_args.begin(), extra_args.end());
+
   std::string error_msg;
   ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
 
@@ -136,12 +139,14 @@
 void DexoptTest::GenerateOdexForTest(const std::string& dex_location,
                                      const std::string& odex_location,
                                      CompilerFilter::Filter filter,
-                                     const char* compilation_reason) {
+                                     const char* compilation_reason,
+                                     const std::vector<std::string>& extra_args) {
   GenerateOatForTest(dex_location,
                      odex_location,
                      filter,
                      /*with_alternate_image=*/ false,
-                     compilation_reason);
+                     compilation_reason,
+                     extra_args);
 }
 
 void DexoptTest::GenerateOatForTest(const char* dex_location,
diff --git a/runtime/dexopt_test.h b/runtime/dexopt_test.h
index efbdcba..026fe55 100644
--- a/runtime/dexopt_test.h
+++ b/runtime/dexopt_test.h
@@ -42,13 +42,15 @@
                           const std::string& oat_location,
                           CompilerFilter::Filter filter,
                           bool with_alternate_image,
-                          const char* compilation_reason = nullptr);
+                          const char* compilation_reason = nullptr,
+                          const std::vector<std::string>& extra_args = {});
 
   // Generate an odex file for the purposes of test.
   void GenerateOdexForTest(const std::string& dex_location,
                            const std::string& odex_location,
                            CompilerFilter::Filter filter,
-                           const char* compilation_reason = nullptr);
+                           const char* compilation_reason = nullptr,
+                          const std::vector<std::string>& extra_args = {});
 
   // Generate an oat file for the given dex location in its oat location (under
   // the dalvik cache).
diff --git a/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc b/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
index 2431bce..d06dbcb 100644
--- a/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
@@ -16,7 +16,6 @@
 
 #include "base/logging.h"  // For VLOG_IS_ON.
 #include "base/mutex.h"
-#include "base/systrace.h"
 #include "callee_save_frame.h"
 #include "interpreter/interpreter.h"
 #include "obj_ptr-inl.h"  // TODO: Find the other include that isn't complete, and clean this up.
@@ -41,13 +40,10 @@
 
   self->AssertHasDeoptimizationContext();
   QuickExceptionHandler exception_handler(self, true);
-  {
-    ScopedTrace trace(std::string("Deoptimization ") + GetDeoptimizationKindName(kind));
-    if (single_frame) {
-      exception_handler.DeoptimizeSingleFrame(kind);
-    } else {
-      exception_handler.DeoptimizeStack();
-    }
+  if (single_frame) {
+    exception_handler.DeoptimizeSingleFrame(kind);
+  } else {
+    exception_handler.DeoptimizeStack();
   }
   uintptr_t return_pc = exception_handler.UpdateInstrumentationStack();
   if (exception_handler.IsFullFragmentDone()) {
diff --git a/runtime/fault_handler.h b/runtime/fault_handler.h
index d3be51f..f6cf2d7 100644
--- a/runtime/fault_handler.h
+++ b/runtime/fault_handler.h
@@ -23,8 +23,8 @@
 
 #include <vector>
 
-#include "base/globals.h"  // For CanDoImplicitNullCheckOn.
 #include "base/locks.h"  // For annotalysis.
+#include "runtime_globals.h"  // For CanDoImplicitNullCheckOn.
 
 namespace art {
 
diff --git a/runtime/gc/accounting/bitmap.h b/runtime/gc/accounting/bitmap.h
index bdc686e..68f2d04 100644
--- a/runtime/gc/accounting/bitmap.h
+++ b/runtime/gc/accounting/bitmap.h
@@ -23,9 +23,9 @@
 #include <set>
 #include <vector>
 
-#include "base/globals.h"
 #include "base/locks.h"
 #include "base/mem_map.h"
+#include "runtime_globals.h"
 
 namespace art {
 
diff --git a/runtime/gc/accounting/card_table.h b/runtime/gc/accounting/card_table.h
index c99ed4b..30c4386 100644
--- a/runtime/gc/accounting/card_table.h
+++ b/runtime/gc/accounting/card_table.h
@@ -19,9 +19,9 @@
 
 #include <memory>
 
-#include "base/globals.h"
 #include "base/locks.h"
 #include "base/mem_map.h"
+#include "runtime_globals.h"
 
 namespace art {
 
diff --git a/runtime/gc/accounting/mod_union_table.h b/runtime/gc/accounting/mod_union_table.h
index 8c471bc..011e95c 100644
--- a/runtime/gc/accounting/mod_union_table.h
+++ b/runtime/gc/accounting/mod_union_table.h
@@ -18,12 +18,12 @@
 #define ART_RUNTIME_GC_ACCOUNTING_MOD_UNION_TABLE_H_
 
 #include "base/allocator.h"
-#include "base/globals.h"
 #include "base/safe_map.h"
 #include "base/tracking_safe_map.h"
 #include "bitmap.h"
 #include "card_table.h"
 #include "mirror/object_reference.h"
+#include "runtime_globals.h"
 
 #include <set>
 #include <vector>
diff --git a/runtime/gc/accounting/read_barrier_table.h b/runtime/gc/accounting/read_barrier_table.h
index 2e42f8d..44cdb5e 100644
--- a/runtime/gc/accounting/read_barrier_table.h
+++ b/runtime/gc/accounting/read_barrier_table.h
@@ -20,10 +20,10 @@
 #include <sys/mman.h>  // For the PROT_* and MAP_* constants.
 
 #include "base/bit_utils.h"
-#include "base/globals.h"
 #include "base/locks.h"
 #include "base/mem_map.h"
 #include "gc/space/space.h"
+#include "runtime_globals.h"
 
 namespace art {
 namespace gc {
diff --git a/runtime/gc/accounting/remembered_set.h b/runtime/gc/accounting/remembered_set.h
index 469074f..3525667 100644
--- a/runtime/gc/accounting/remembered_set.h
+++ b/runtime/gc/accounting/remembered_set.h
@@ -18,9 +18,9 @@
 #define ART_RUNTIME_GC_ACCOUNTING_REMEMBERED_SET_H_
 
 #include "base/allocator.h"
-#include "base/globals.h"
 #include "base/locks.h"
 #include "base/safe_map.h"
+#include "runtime_globals.h"
 
 #include <set>
 #include <vector>
diff --git a/runtime/gc/accounting/space_bitmap.h b/runtime/gc/accounting/space_bitmap.h
index 8561f06..6ca254a 100644
--- a/runtime/gc/accounting/space_bitmap.h
+++ b/runtime/gc/accounting/space_bitmap.h
@@ -23,9 +23,9 @@
 #include <set>
 #include <vector>
 
-#include "base/globals.h"
 #include "base/locks.h"
 #include "base/mem_map.h"
+#include "runtime_globals.h"
 
 namespace art {
 
diff --git a/runtime/gc/accounting/space_bitmap_test.cc b/runtime/gc/accounting/space_bitmap_test.cc
index 22529b8..9f355e3 100644
--- a/runtime/gc/accounting/space_bitmap_test.cc
+++ b/runtime/gc/accounting/space_bitmap_test.cc
@@ -19,9 +19,9 @@
 #include <stdint.h>
 #include <memory>
 
-#include "base/globals.h"
 #include "base/mutex.h"
 #include "common_runtime_test.h"
+#include "runtime_globals.h"
 #include "space_bitmap-inl.h"
 
 namespace art {
diff --git a/runtime/gc/allocator/dlmalloc.cc b/runtime/gc/allocator/dlmalloc.cc
index 11ad8a8..79d4fbf 100644
--- a/runtime/gc/allocator/dlmalloc.cc
+++ b/runtime/gc/allocator/dlmalloc.cc
@@ -60,8 +60,8 @@
 
 #include <sys/mman.h>
 
-#include "base/globals.h"
 #include "base/utils.h"
+#include "runtime_globals.h"
 
 extern "C" void DlmallocMadviseCallback(void* start, void* end, size_t used_bytes, void* arg) {
   // Is this chunk in use?
diff --git a/runtime/gc/allocator/rosalloc.h b/runtime/gc/allocator/rosalloc.h
index bf26aea..0906295 100644
--- a/runtime/gc/allocator/rosalloc.h
+++ b/runtime/gc/allocator/rosalloc.h
@@ -30,9 +30,9 @@
 
 #include "base/allocator.h"
 #include "base/bit_utils.h"
-#include "base/globals.h"
 #include "base/mem_map.h"
 #include "base/mutex.h"
+#include "runtime_globals.h"
 #include "thread.h"
 
 namespace art {
diff --git a/runtime/gc/gc_cause.cc b/runtime/gc/gc_cause.cc
index ee7ac7d..8b4bac2 100644
--- a/runtime/gc/gc_cause.cc
+++ b/runtime/gc/gc_cause.cc
@@ -18,8 +18,8 @@
 
 #include <android-base/logging.h>
 
-#include "base/globals.h"
 #include "base/macros.h"
+#include "runtime_globals.h"
 
 #include <ostream>
 
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 8d19cd0..d699da0 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -3798,7 +3798,7 @@
   if (!Runtime::Current()->IsShuttingDown(self)) {
     // Wait for any GCs currently running to finish.
     if (WaitForGcToComplete(cause, self) == collector::kGcTypeNone) {
-      // If the we can't run the GC type we wanted to run, find the next appropriate one and try
+      // If we can't run the GC type we wanted to run, find the next appropriate one and try
       // that instead. E.g. can't do partial, so do full instead.
       collector::GcType next_gc_type = next_gc_type_;
       // If forcing full and next gc type is sticky, override with a non-sticky type.
@@ -3977,8 +3977,13 @@
 // If weighted java + native memory use exceeds our target by kStopForNativeFactor, and
 // newly allocated memory exceeds kHugeNativeAlloc, we wait for GC to complete to avoid
 // running out of memory.
-static constexpr float kStopForNativeFactor = 2.0;
-static constexpr size_t kHugeNativeAllocs = 200*1024*1024;
+static constexpr float kStopForNativeFactor = 4.0;
+// TODO: Allow this to be tuned. We want this much smaller for some apps, like Calculator.
+// But making it too small can cause jank in apps like launcher that intentionally allocate
+// large amounts of memory in rapid succession. (b/122099093)
+// For now, we punt, and use a value that should be easily large enough to disable this in all
+// questionable setting, but that is clearly too large to be effective for small memory devices.
+static constexpr size_t kHugeNativeAllocs = 1 * GB;
 
 // Return the ratio of the weighted native + java allocated bytes to its target value.
 // A return value > 1.0 means we should collect. Significantly larger values mean we're falling
@@ -3998,8 +4003,9 @@
     size_t new_native_bytes = UnsignedDifference(current_native_bytes, old_native_bytes);
     size_t weighted_native_bytes = new_native_bytes / kNewNativeDiscountFactor
         + old_native_bytes / kOldNativeDiscountFactor;
-    size_t adj_start_bytes = concurrent_start_bytes_
-        + NativeAllocationGcWatermark() / kNewNativeDiscountFactor;
+    size_t add_bytes_allowed = static_cast<size_t>(
+        NativeAllocationGcWatermark() * HeapGrowthMultiplier());
+    size_t adj_start_bytes = concurrent_start_bytes_ + add_bytes_allowed / kNewNativeDiscountFactor;
     return static_cast<float>(GetBytesAllocated() + weighted_native_bytes)
          / static_cast<float>(adj_start_bytes);
   }
@@ -4017,7 +4023,7 @@
         if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
           LOG(INFO) << "Stopping for native allocation, urgency: " << gc_urgency;
         }
-        WaitForGcToComplete(kGcCauseForAlloc, self);
+        WaitForGcToComplete(kGcCauseForNativeAlloc, self);
       }
     } else {
       CollectGarbageInternal(NonStickyGcType(), kGcCauseForNativeAlloc, false);
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 6696cc1..52c9386 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -25,9 +25,7 @@
 #include <android-base/logging.h>
 
 #include "allocator_type.h"
-#include "arch/instruction_set.h"
 #include "base/atomic.h"
-#include "base/globals.h"
 #include "base/macros.h"
 #include "base/mutex.h"
 #include "base/runtime_debug.h"
@@ -43,11 +41,13 @@
 #include "offsets.h"
 #include "process_state.h"
 #include "read_barrier_config.h"
+#include "runtime_globals.h"
 #include "verify_object.h"
 
 namespace art {
 
 class ConditionVariable;
+enum class InstructionSet;
 class IsMarkedVisitor;
 class Mutex;
 class RootVisitor;
@@ -157,7 +157,12 @@
   // Client should call NotifyNativeAllocation every kNotifyNativeInterval allocations.
   // Should be chosen so that time_to_call_mallinfo / kNotifyNativeInterval is on the same order
   // as object allocation time. time_to_call_mallinfo seems to be on the order of 1 usec.
+#ifdef __ANDROID__
   static constexpr uint32_t kNotifyNativeInterval = 32;
+#else
+  // Some host mallinfo() implementations are slow. And memory is less scarce.
+  static constexpr uint32_t kNotifyNativeInterval = 128;
+#endif
 
   // RegisterNativeAllocation checks immediately whether GC is needed if size exceeds the
   // following. kCheckImmediatelyThreshold * kNotifyNativeInterval should be small enough to
@@ -436,6 +441,10 @@
     return process_cpu_start_time_ns_;
   }
 
+  uint64_t GetPostGCLastProcessCpuTime() const {
+    return post_gc_last_process_cpu_time_ns_;
+  }
+
   // Set target ideal heap utilization ratio, implements
   // dalvik.system.VMRuntime.setTargetHeapUtilization.
   void SetTargetHeapUtilization(float target);
@@ -1140,15 +1149,9 @@
   // collect. We collect when a weighted sum of Java memory plus native memory exceeds
   // the similarly weighted sum of the Java heap size target and this value.
   ALWAYS_INLINE size_t NativeAllocationGcWatermark() const {
-    // It probably makes most sense to use a constant multiple of target_footprint_ .
-    // This is a good indication of the live data size, together with the
-    // intended space-time trade-off, as expressed by SetTargetHeapUtilization.
-    // For a fixed target utilization, the amount of GC effort per native
-    // allocated byte remains roughly constant as the Java heap size changes.
-    // But we previously triggered on max_free_ native allocation which is often much
-    // smaller. To avoid unexpected growth, we partially keep that limit in place for now.
-    // TODO: Consider HeapGrowthMultiplier(). Maybe.
-    return std::min(target_footprint_.load(std::memory_order_relaxed), 2 * max_free_);
+    // We keep the traditional limit of max_free_ in place for small heaps,
+    // but allow it to be adjusted upward for large heaps to limit GC overhead.
+    return target_footprint_.load(std::memory_order_relaxed) / 8 + max_free_;
   }
 
   ALWAYS_INLINE void IncrementNumberOfBytesFreedRevoke(size_t freed_bytes_revoke);
diff --git a/runtime/gc/reference_processor.h b/runtime/gc/reference_processor.h
index 17b546a..c1c9a3c 100644
--- a/runtime/gc/reference_processor.h
+++ b/runtime/gc/reference_processor.h
@@ -17,10 +17,10 @@
 #ifndef ART_RUNTIME_GC_REFERENCE_PROCESSOR_H_
 #define ART_RUNTIME_GC_REFERENCE_PROCESSOR_H_
 
-#include "base/globals.h"
 #include "base/locks.h"
 #include "jni.h"
 #include "reference_queue.h"
+#include "runtime_globals.h"
 
 namespace art {
 
diff --git a/runtime/gc/reference_queue.h b/runtime/gc/reference_queue.h
index 53518cc..90f0be7 100644
--- a/runtime/gc/reference_queue.h
+++ b/runtime/gc/reference_queue.h
@@ -22,12 +22,12 @@
 #include <vector>
 
 #include "base/atomic.h"
-#include "base/globals.h"
 #include "base/locks.h"
 #include "base/timing_logger.h"
 #include "jni.h"
 #include "obj_ptr.h"
 #include "offsets.h"
+#include "runtime_globals.h"
 #include "thread_pool.h"
 
 namespace art {
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 64fd3cd..4a2dbf5 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -25,6 +25,7 @@
 #include "android-base/stringprintf.h"
 #include "android-base/strings.h"
 
+#include "arch/instruction_set.h"
 #include "art_field-inl.h"
 #include "art_method-inl.h"
 #include "base/array_ref.h"
@@ -341,6 +342,10 @@
     return address - source_ < length_;
   }
 
+  bool InDest(const void* dest) const {
+    return InDest(reinterpret_cast<uintptr_t>(dest));
+  }
+
   bool InDest(uintptr_t address) const {
     return address - dest_ < length_;
   }
@@ -381,11 +386,11 @@
             << reinterpret_cast<const void*>(reloc.Dest() + reloc.Length()) << ")";
 }
 
-template <PointerSize kPointerSize, typename ReferenceVisitor>
+template <PointerSize kPointerSize, typename HeapVisitor, typename NativeVisitor>
 class ImageSpace::PatchObjectVisitor final {
  public:
-  explicit PatchObjectVisitor(ReferenceVisitor reference_visitor)
-      : reference_visitor_(reference_visitor) {}
+  explicit PatchObjectVisitor(HeapVisitor heap_visitor, NativeVisitor native_visitor)
+      : heap_visitor_(heap_visitor), native_visitor_(native_visitor) {}
 
   void VisitClass(mirror::Class* klass) REQUIRES_SHARED(Locks::mutator_lock_) {
     // A mirror::Class object consists of
@@ -445,12 +450,8 @@
   }
 
   template <typename T>
-  T* operator()(T* ptr, void** dest_addr ATTRIBUTE_UNUSED) const
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    if (ptr != nullptr) {
-      ptr = reference_visitor_(ptr);
-    }
-    return ptr;
+  T* operator()(T* ptr, void** dest_addr ATTRIBUTE_UNUSED) const {
+    return (ptr != nullptr) ? native_visitor_(ptr) : nullptr;
   }
 
   void VisitPointerArray(mirror::PointerArray* pointer_array)
@@ -526,7 +527,7 @@
     T* old_value = root->template Read<kWithoutReadBarrier>();
     DCHECK(kMayBeNull || old_value != nullptr);
     if (!kMayBeNull || old_value != nullptr) {
-      *root = GcRoot<T>(reference_visitor_(old_value));
+      *root = GcRoot<T>(heap_visitor_(old_value));
     }
   }
 
@@ -537,7 +538,7 @@
       T* old_value = reinterpret_cast64<T*>(*raw_entry);
       DCHECK(kMayBeNull || old_value != nullptr);
       if (!kMayBeNull || old_value != nullptr) {
-        T* new_value = reference_visitor_(old_value);
+        T* new_value = native_visitor_(old_value);
         *raw_entry = reinterpret_cast64<uint64_t>(new_value);
       }
     } else {
@@ -545,7 +546,7 @@
       T* old_value = reinterpret_cast32<T*>(*raw_entry);
       DCHECK(kMayBeNull || old_value != nullptr);
       if (!kMayBeNull || old_value != nullptr) {
-        T* new_value = reference_visitor_(old_value);
+        T* new_value = native_visitor_(old_value);
         *raw_entry = reinterpret_cast32<uint32_t>(new_value);
       }
     }
@@ -558,7 +559,7 @@
         object->GetFieldObject<mirror::Object, kVerifyNone, kWithoutReadBarrier>(offset);
     DCHECK(kMayBeNull || old_value != nullptr);
     if (!kMayBeNull || old_value != nullptr) {
-      mirror::Object* new_value = reference_visitor_(old_value);
+      mirror::Object* new_value = heap_visitor_(old_value);
       object->SetFieldObjectWithoutWriteBarrier</*kTransactionActive=*/ false,
                                                 /*kCheckTransaction=*/ true,
                                                 kVerifyNone>(offset, new_value);
@@ -582,7 +583,7 @@
     mirror::NativeDexCachePair<T> pair =
         mirror::DexCache::GetNativePairPtrSize(array, index, kPointerSize);
     if (pair.object != nullptr) {
-      pair.object = reference_visitor_(pair.object);
+      pair.object = native_visitor_(pair.object);
       mirror::DexCache::SetNativePairPtrSize(array, index, pair, kPointerSize);
     }
   }
@@ -605,7 +606,7 @@
         reinterpret_cast64<EntryType*>(dex_cache->GetField64<kVerifyNone>(array_offset));
     DCHECK_EQ(old_array != nullptr, size != 0u);
     if (old_array != nullptr) {
-      EntryType* new_array = reference_visitor_(old_array);
+      EntryType* new_array = native_visitor_(old_array);
       dex_cache->SetField64<kVerifyNone>(array_offset, reinterpret_cast64<uint64_t>(new_array));
       for (uint32_t i = 0; i != size; ++i) {
         FixupDexCacheArrayEntry(new_array, i);
@@ -614,7 +615,11 @@
   }
 
  private:
-  ReferenceVisitor reference_visitor_;
+  // Heap objects visitor.
+  HeapVisitor heap_visitor_;
+
+  // Native objects visitor.
+  NativeVisitor native_visitor_;
 };
 
 template <typename ObjectVisitor>
@@ -828,7 +833,7 @@
 
     // GetImageBegin is the preferred address to map the image. If we manage to map the
     // image at the image begin, the amount of fixup work required is minimized.
-    // If it is pic we will retry with error_msg for the failure case. Pass a null error_msg to
+    // If it is pic we will retry with error_msg for the2 failure case. Pass a null error_msg to
     // avoid reading proc maps for a mapping failure and slowing everything down.
     // For the boot image, we have already reserved the memory and we load the image
     // into the `image_reservation`.
@@ -981,12 +986,11 @@
         auto function = [&](Thread*) {
           const uint64_t start2 = NanoTime();
           ScopedTrace trace("LZ4 decompress block");
-          if (!block.Decompress(/*out_ptr=*/map.Begin(),
-                                /*in_ptr=*/temp_map.Begin(),
-                                error_msg)) {
-            if (error_msg != nullptr) {
-              *error_msg = "Failed to decompress image block " + *error_msg;
-            }
+          bool result = block.Decompress(/*out_ptr=*/map.Begin(),
+                                         /*in_ptr=*/temp_map.Begin(),
+                                         error_msg);
+          if (!result && error_msg != nullptr) {
+            *error_msg = "Failed to decompress image block " + *error_msg;
           }
           VLOG(image) << "Decompress block " << block.GetDataSize() << " -> "
                       << block.GetImageSize() << " in " << PrettyDuration(NanoTime() - start2);
@@ -1011,70 +1015,51 @@
     return map;
   }
 
-  class FixupVisitor : public ValueObject {
+  class EmptyRange {
    public:
-    FixupVisitor(const RelocationRange& boot_image,
-                 const RelocationRange& app_image,
-                 const RelocationRange& app_oat)
-        : boot_image_(boot_image),
-          app_image_(app_image),
-          app_oat_(app_oat) {}
+    ALWAYS_INLINE bool InSource(uintptr_t) const { return false; }
+    ALWAYS_INLINE bool InDest(uintptr_t) const { return false; }
+    ALWAYS_INLINE uintptr_t ToDest(uintptr_t) const { UNREACHABLE(); }
+  };
+
+  template <typename Range0, typename Range1 = EmptyRange, typename Range2 = EmptyRange>
+  class ForwardAddress {
+   public:
+    ForwardAddress(const Range0& range0 = Range0(),
+                   const Range1& range1 = Range1(),
+                   const Range2& range2 = Range2())
+        : range0_(range0), range1_(range1), range2_(range2) {}
 
     // Return the relocated address of a heap object.
     // Null checks must be performed in the caller (for performance reasons).
     template <typename T>
-    ALWAYS_INLINE T* ForwardObject(T* src) const {
+    ALWAYS_INLINE T* operator()(T* src) const {
       DCHECK(src != nullptr);
       const uintptr_t uint_src = reinterpret_cast<uintptr_t>(src);
-      if (boot_image_.InSource(uint_src)) {
-        return reinterpret_cast<T*>(boot_image_.ToDest(uint_src));
+      if (range2_.InSource(uint_src)) {
+        return reinterpret_cast<T*>(range2_.ToDest(uint_src));
       }
-      // Since we are fixing up the app image, there should only be pointers to the app image and
-      // boot image.
-      DCHECK(app_image_.InSource(uint_src)) << reinterpret_cast<const void*>(src);
-      return reinterpret_cast<T*>(app_image_.ToDest(uint_src));
-    }
-
-    // Return the relocated address of a code pointer (contained by an oat file).
-    // Null checks must be performed in the caller (for performance reasons).
-    ALWAYS_INLINE const void* ForwardCode(const void* src) const {
-      DCHECK(src != nullptr);
-      const uintptr_t uint_src = reinterpret_cast<uintptr_t>(src);
-      if (boot_image_.InSource(uint_src)) {
-        return reinterpret_cast<const void*>(boot_image_.ToDest(uint_src));
+      if (range1_.InSource(uint_src)) {
+        return reinterpret_cast<T*>(range1_.ToDest(uint_src));
       }
-      DCHECK(app_oat_.InSource(uint_src)) << src;
-      return reinterpret_cast<const void*>(app_oat_.ToDest(uint_src));
+      CHECK(range0_.InSource(uint_src))
+          << reinterpret_cast<const void*>(src) << " not in "
+          << reinterpret_cast<const void*>(range0_.Source()) << "-"
+          << reinterpret_cast<const void*>(range0_.Source() + range0_.Length());
+      return reinterpret_cast<T*>(range0_.ToDest(uint_src));
     }
 
-    // Must be called on pointers that already have been relocated to the destination relocation.
-    ALWAYS_INLINE bool IsInAppImage(mirror::Object* object) const {
-      return app_image_.InDest(reinterpret_cast<uintptr_t>(object));
-    }
-
-   protected:
-    // Source section.
-    const RelocationRange boot_image_;
-    const RelocationRange app_image_;
-    const RelocationRange app_oat_;
+   private:
+    const Range0 range0_;
+    const Range1 range1_;
+    const Range2 range2_;
   };
 
-  // Adapt for mirror::Class::FixupNativePointers.
-  class FixupObjectAdapter : public FixupVisitor {
+  template <typename Forward>
+  class FixupRootVisitor {
    public:
     template<typename... Args>
-    explicit FixupObjectAdapter(Args... args) : FixupVisitor(args...) {}
-
-    template <typename T>
-    T* operator()(T* obj, void** dest_addr ATTRIBUTE_UNUSED = nullptr) const {
-      return ForwardObject(obj);
-    }
-  };
-
-  class FixupRootVisitor : public FixupVisitor {
-   public:
-    template<typename... Args>
-    explicit FixupRootVisitor(Args... args) : FixupVisitor(args...) {}
+    explicit FixupRootVisitor(Args... args) : forward_(args...) {}
 
     ALWAYS_INLINE void VisitRootIfNonNull(mirror::CompressedReference<mirror::Object>* root) const
         REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -1086,19 +1071,22 @@
     ALWAYS_INLINE void VisitRoot(mirror::CompressedReference<mirror::Object>* root) const
         REQUIRES_SHARED(Locks::mutator_lock_) {
       mirror::Object* ref = root->AsMirrorPtr();
-      mirror::Object* new_ref = ForwardObject(ref);
+      mirror::Object* new_ref = forward_(ref);
       if (ref != new_ref) {
         root->Assign(new_ref);
       }
     }
+
+   private:
+    Forward forward_;
   };
 
-  class FixupObjectVisitor : public FixupVisitor {
+  template <typename Forward>
+  class FixupObjectVisitor {
    public:
-    template<typename... Args>
-    explicit FixupObjectVisitor(gc::accounting::ContinuousSpaceBitmap* visited, Args... args)
-        : FixupVisitor(args...),
-          visited_(visited) {}
+    explicit FixupObjectVisitor(gc::accounting::ContinuousSpaceBitmap* visited,
+                                const Forward& forward)
+        : visited_(visited), forward_(forward) {}
 
     // Fix up separately since we also need to fix up method entrypoints.
     ALWAYS_INLINE void VisitRootIfNonNull(
@@ -1117,8 +1105,7 @@
       if (ref != nullptr) {
         // Use SetFieldObjectWithoutWriteBarrier to avoid card marking since we are writing to the
         // image.
-        obj->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(
-            offset, ForwardObject(ref));
+        obj->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(offset, forward_(ref));
       }
     }
 
@@ -1130,7 +1117,7 @@
       if (obj != nullptr) {
         ref->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(
             mirror::Reference::ReferentOffset(),
-            ForwardObject(obj));
+            forward_(obj));
       }
     }
 
@@ -1147,79 +1134,61 @@
 
    private:
     gc::accounting::ContinuousSpaceBitmap* const visited_;
+    Forward forward_;
   };
 
-  class ForwardObjectAdapter {
-   public:
-    ALWAYS_INLINE explicit ForwardObjectAdapter(const FixupVisitor* visitor) : visitor_(visitor) {}
-
-    template <typename T>
-    ALWAYS_INLINE T* operator()(T* src) const {
-      return visitor_->ForwardObject(src);
-    }
-
-   private:
-    const FixupVisitor* const visitor_;
-  };
-
-  class ForwardCodeAdapter {
-   public:
-    ALWAYS_INLINE explicit ForwardCodeAdapter(const FixupVisitor* visitor)
-        : visitor_(visitor) {}
-
-    template <typename T>
-    ALWAYS_INLINE T* operator()(T* src) const {
-      return visitor_->ForwardCode(src);
-    }
-
-   private:
-    const FixupVisitor* const visitor_;
-  };
-
-  class FixupArtMethodVisitor : public FixupVisitor, public ArtMethodVisitor {
+  template <typename ForwardObject, typename ForwardNative, typename ForwardCode>
+  class FixupArtMethodVisitor : public ArtMethodVisitor {
    public:
     template<typename... Args>
-    explicit FixupArtMethodVisitor(bool fixup_heap_objects, PointerSize pointer_size, Args... args)
-        : FixupVisitor(args...),
-          fixup_heap_objects_(fixup_heap_objects),
-          pointer_size_(pointer_size) {}
+    explicit FixupArtMethodVisitor(PointerSize pointer_size,
+                                   const ForwardObject& forward_object,
+                                   const ForwardNative& forward_native,
+                                   const ForwardCode& forward_code)
+        : pointer_size_(pointer_size),
+          forward_object_(forward_object),
+          forward_native_(forward_native),
+          forward_code_(forward_code) {}
 
     void Visit(ArtMethod* method) override NO_THREAD_SAFETY_ANALYSIS {
       // TODO: Separate visitor for runtime vs normal methods.
       if (UNLIKELY(method->IsRuntimeMethod())) {
         ImtConflictTable* table = method->GetImtConflictTable(pointer_size_);
         if (table != nullptr) {
-          ImtConflictTable* new_table = ForwardObject(table);
+          ImtConflictTable* new_table = forward_native_(table);
           if (table != new_table) {
             method->SetImtConflictTable(new_table, pointer_size_);
           }
         }
         const void* old_code = method->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size_);
-        const void* new_code = ForwardCode(old_code);
+        const void* new_code = forward_code_(old_code);
         if (old_code != new_code) {
           method->SetEntryPointFromQuickCompiledCodePtrSize(new_code, pointer_size_);
         }
       } else {
-        if (fixup_heap_objects_) {
-          method->UpdateObjectsForImageRelocation(ForwardObjectAdapter(this));
-        }
-        method->UpdateEntrypoints(ForwardCodeAdapter(this), pointer_size_);
+        method->UpdateObjectsForImageRelocation(forward_object_);
+        method->UpdateEntrypoints(forward_code_, pointer_size_);
       }
     }
 
    private:
-    const bool fixup_heap_objects_;
     const PointerSize pointer_size_;
+    const ForwardObject forward_object_;
+    const ForwardNative forward_native_;
+    const ForwardCode forward_code_;
   };
 
-  class FixupArtFieldVisitor : public FixupVisitor, public ArtFieldVisitor {
+  template <typename Forward>
+  class FixupArtFieldVisitor : public ArtFieldVisitor {
    public:
-    template<typename... Args>
-    explicit FixupArtFieldVisitor(Args... args) : FixupVisitor(args...) {}
+    explicit FixupArtFieldVisitor(Forward forward) : forward_(forward) {}
 
     void Visit(ArtField* field) override NO_THREAD_SAFETY_ANALYSIS {
-      field->UpdateObjects(ForwardObjectAdapter(this));
+      field->UpdateObjects(forward_);
     }
+
+   private:
+    Forward forward_;
   };
 
   // Relocate an image space mapped at target_base which possibly used to be at a different base
@@ -1256,30 +1225,49 @@
                                 static_cast<uint64_t>(image_header_boot_image_size));
       return false;
     }
+    const ImageSection& objects_section = image_header.GetObjectsSection();
+    // Where the app image objects are mapped to.
+    uint8_t* objects_location = target_base + objects_section.Offset();
     TimingLogger logger(__FUNCTION__, true, false);
     RelocationRange boot_image(image_header.GetBootImageBegin(),
                                boot_image_begin,
                                boot_image_size);
-    RelocationRange app_image(reinterpret_cast<uintptr_t>(image_header.GetImageBegin()),
-                              reinterpret_cast<uintptr_t>(target_base),
-                              image_header.GetImageSize());
+    // Metadata is everything after the objects section, use exclusion to be safe.
+    RelocationRange app_image_metadata(
+        reinterpret_cast<uintptr_t>(image_header.GetImageBegin()) + objects_section.End(),
+        reinterpret_cast<uintptr_t>(target_base) + objects_section.End(),
+        image_header.GetImageSize() - objects_section.End());
+    // App image heap objects, may be mapped in the heap.
+    RelocationRange app_image_objects(
+        reinterpret_cast<uintptr_t>(image_header.GetImageBegin()) + objects_section.Offset(),
+        reinterpret_cast<uintptr_t>(objects_location),
+        objects_section.Size());
     // Use the oat data section since this is where the OatFile::Begin is.
     RelocationRange app_oat(reinterpret_cast<uintptr_t>(image_header.GetOatDataBegin()),
                             // Not necessarily in low 4GB.
                             reinterpret_cast<uintptr_t>(app_oat_file->Begin()),
                             image_header.GetOatDataEnd() - image_header.GetOatDataBegin());
-    VLOG(image) << "App image " << app_image;
+    VLOG(image) << "App image metadata " << app_image_metadata;
+    VLOG(image) << "App image objects " << app_image_objects;
     VLOG(image) << "App oat " << app_oat;
     VLOG(image) << "Boot image " << boot_image;
     // True if we need to fixup any heap pointers.
-    const bool fixup_image = boot_image.Delta() != 0 || app_image.Delta() != 0;
+    const bool fixup_image = boot_image.Delta() != 0 || app_image_metadata.Delta() != 0 ||
+        app_image_objects.Delta() != 0;
     if (!fixup_image) {
       // Nothing to fix up.
       return true;
     }
     ScopedDebugDisallowReadBarriers sddrb(Thread::Current());
-    FixupObjectAdapter fixup_adapter(boot_image, app_image, app_oat);
-    PatchObjectVisitor<kPointerSize, FixupObjectAdapter> patch_object_visitor(fixup_adapter);
+
+    using ForwardObject = ForwardAddress<RelocationRange, RelocationRange>;
+    ForwardObject forward_object(boot_image, app_image_objects);
+    ForwardObject forward_metadata(boot_image, app_image_metadata);
+    using ForwardCode = ForwardAddress<RelocationRange, RelocationRange>;
+    ForwardCode forward_code(boot_image, app_oat);
+    PatchObjectVisitor<kPointerSize, ForwardObject, ForwardCode> patch_object_visitor(
+        forward_object,
+        forward_metadata);
     if (fixup_image) {
       // Two pass approach, fix up all classes first, then fix up non class-objects.
       // The visited bitmap is used to ensure that pointer arrays are not forwarded twice.
@@ -1287,13 +1275,12 @@
           gc::accounting::ContinuousSpaceBitmap::Create("Relocate bitmap",
                                                         target_base,
                                                         image_header.GetImageSize()));
-      FixupObjectVisitor fixup_object_visitor(visited_bitmap.get(), boot_image, app_image, app_oat);
       {
         TimingLogger::ScopedTiming timing("Fixup classes", &logger);
         const auto& class_table_section = image_header.GetClassTableSection();
         if (class_table_section.Size() > 0u) {
           ScopedObjectAccess soa(Thread::Current());
-          ClassTableVisitor class_table_visitor(fixup_adapter);
+          ClassTableVisitor class_table_visitor(forward_object);
           size_t read_count = 0u;
           const uint8_t* data = target_base + class_table_section.Offset();
           // We avoid making a copy of the data since we want modifications to be propagated to the
@@ -1302,7 +1289,7 @@
           for (ClassTable::TableSlot& slot : temp_set) {
             slot.VisitRoot(class_table_visitor);
             mirror::Class* klass = slot.Read<kWithoutReadBarrier>();
-            if (!fixup_adapter.IsInAppImage(klass)) {
+            if (!app_image_objects.InDest(klass)) {
               continue;
             }
             const bool already_marked = visited_bitmap->Set(klass);
@@ -1311,12 +1298,12 @@
             // Then patch the non-embedded vtable and iftable.
             mirror::PointerArray* vtable = klass->GetVTable<kVerifyNone, kWithoutReadBarrier>();
             if (vtable != nullptr &&
-                fixup_object_visitor.IsInAppImage(vtable) &&
+                app_image_objects.InDest(vtable) &&
                 !visited_bitmap->Set(vtable)) {
               patch_object_visitor.VisitPointerArray(vtable);
             }
             auto* iftable = klass->GetIfTable<kVerifyNone, kWithoutReadBarrier>();
-            if (iftable != nullptr && fixup_object_visitor.IsInAppImage(iftable)) {
+            if (iftable != nullptr && app_image_objects.InDest(iftable)) {
               // Avoid processing the fields of iftable since we will process them later anyways
               // below.
               int32_t ifcount = klass->GetIfTableCount<kVerifyNone>();
@@ -1325,9 +1312,8 @@
                     iftable->GetMethodArrayOrNull<kVerifyNone, kWithoutReadBarrier>(i);
                 if (unpatched_ifarray != nullptr) {
                   // The iftable has not been patched, so we need to explicitly adjust the pointer.
-                  mirror::PointerArray* ifarray = fixup_adapter(unpatched_ifarray);
-                  if (fixup_object_visitor.IsInAppImage(ifarray) &&
-                      !visited_bitmap->Set(ifarray)) {
+                  mirror::PointerArray* ifarray = forward_object(unpatched_ifarray);
+                  if (app_image_objects.InDest(ifarray) && !visited_bitmap->Set(ifarray)) {
                     patch_object_visitor.VisitPointerArray(ifarray);
                   }
                 }
@@ -1342,14 +1328,14 @@
       TimingLogger::ScopedTiming timing("Fixup objects", &logger);
       ScopedObjectAccess soa(Thread::Current());
       // Need to update the image to be at the target base.
-      const ImageSection& objects_section = image_header.GetObjectsSection();
       uintptr_t objects_begin = reinterpret_cast<uintptr_t>(target_base + objects_section.Offset());
       uintptr_t objects_end = reinterpret_cast<uintptr_t>(target_base + objects_section.End());
+      FixupObjectVisitor<ForwardObject> fixup_object_visitor(visited_bitmap.get(), forward_object);
       bitmap->VisitMarkedRange(objects_begin, objects_end, fixup_object_visitor);
       // Fixup image roots.
-      CHECK(app_image.InSource(reinterpret_cast<uintptr_t>(
+      CHECK(app_image_objects.InSource(reinterpret_cast<uintptr_t>(
           image_header.GetImageRoots<kWithoutReadBarrier>().Ptr())));
-      image_header.RelocateImageObjects(app_image.Delta());
+      image_header.RelocateImageObjects(app_image_objects.Delta());
       CHECK_EQ(image_header.GetImageBegin(), target_base);
       // Fix up dex cache DexFile pointers.
       auto* dex_caches = image_header.GetImageRoot<kWithoutReadBarrier>(ImageHeader::kDexCaches)->
@@ -1363,27 +1349,26 @@
     {
       // Only touches objects in the app image, no need for mutator lock.
       TimingLogger::ScopedTiming timing("Fixup methods", &logger);
-      FixupArtMethodVisitor method_visitor(fixup_image,
-                                           kPointerSize,
-                                           boot_image,
-                                           app_image,
-                                           app_oat);
+      FixupArtMethodVisitor method_visitor(kPointerSize,
+                                           forward_object,
+                                           forward_metadata,
+                                           forward_code);
       image_header.VisitPackedArtMethods(&method_visitor, target_base, kPointerSize);
     }
     if (fixup_image) {
       {
         // Only touches objects in the app image, no need for mutator lock.
         TimingLogger::ScopedTiming timing("Fixup fields", &logger);
-        FixupArtFieldVisitor field_visitor(boot_image, app_image, app_oat);
+        FixupArtFieldVisitor field_visitor(forward_object);
         image_header.VisitPackedArtFields(&field_visitor, target_base);
       }
       {
         TimingLogger::ScopedTiming timing("Fixup imt", &logger);
-        image_header.VisitPackedImTables(fixup_adapter, target_base, kPointerSize);
+        image_header.VisitPackedImTables(forward_metadata, target_base, kPointerSize);
       }
       {
         TimingLogger::ScopedTiming timing("Fixup conflict tables", &logger);
-        image_header.VisitPackedImtConflictTables(fixup_adapter, target_base, kPointerSize);
+        image_header.VisitPackedImtConflictTables(forward_metadata, target_base, kPointerSize);
       }
       // In the app image case, the image methods are actually in the boot image.
       image_header.RelocateImageMethods(boot_image.Delta());
@@ -1396,12 +1381,11 @@
         InternTable temp_intern_table;
         // Note that we require that ReadFromMemory does not make an internal copy of the elements
         // so that the VisitRoots() will update the memory directly rather than the copies.
-        FixupRootVisitor root_visitor(boot_image, app_image, app_oat);
         temp_intern_table.AddTableFromMemory(target_base + intern_table_section.Offset(),
                                              [&](InternTable::UnorderedSet& strings)
             REQUIRES_SHARED(Locks::mutator_lock_) {
           for (GcRoot<mirror::String>& root : strings) {
-            root = GcRoot<mirror::String>(fixup_adapter(root.Read<kWithoutReadBarrier>()));
+            root = GcRoot<mirror::String>(forward_object(root.Read<kWithoutReadBarrier>()));
           }
         }, /*is_boot_image=*/ false);
       }
@@ -1618,9 +1602,9 @@
             "Marked objects",
             spaces.front()->Begin(),
             spaces.back()->End() - spaces.front()->Begin()));
-    using PatchRelocateVisitor = PatchObjectVisitor<kPointerSize, RelocateVisitor>;
+    using PatchRelocateVisitor = PatchObjectVisitor<kPointerSize, RelocateVisitor, RelocateVisitor>;
     RelocateVisitor relocate_visitor(diff);
-    PatchRelocateVisitor patch_object_visitor(relocate_visitor);
+    PatchRelocateVisitor patch_object_visitor(relocate_visitor, relocate_visitor);
 
     mirror::Class* dcheck_class_class = nullptr;  // Used only for a DCHECK().
     for (size_t s = 0u, size = spaces.size(); s != size; ++s) {
diff --git a/runtime/gc/space/image_space.h b/runtime/gc/space/image_space.h
index 14e364a..bb19097 100644
--- a/runtime/gc/space/image_space.h
+++ b/runtime/gc/space/image_space.h
@@ -17,7 +17,6 @@
 #ifndef ART_RUNTIME_GC_SPACE_IMAGE_SPACE_H_
 #define ART_RUNTIME_GC_SPACE_IMAGE_SPACE_H_
 
-#include "arch/instruction_set.h"
 #include "gc/accounting/space_bitmap.h"
 #include "image.h"
 #include "space.h"
@@ -26,6 +25,7 @@
 
 template <typename T> class ArrayRef;
 class DexFile;
+enum class InstructionSet;
 class OatFile;
 
 namespace gc {
@@ -216,7 +216,7 @@
   class PatchArtFieldVisitor;
   template <PointerSize kPointerSize, typename PatchObjectVisitor, typename PatchCodeVisitor>
   class PatchArtMethodVisitor;
-  template <PointerSize kPointerSize, typename ReferenceVisitor>
+  template <PointerSize kPointerSize, typename HeapVisitor, typename NativeVisitor>
   class PatchObjectVisitor;
 
   DISALLOW_COPY_AND_ASSIGN(ImageSpace);
diff --git a/runtime/gc/space/image_space_fs.h b/runtime/gc/space/image_space_fs.h
index 14deb6f..262c6e0 100644
--- a/runtime/gc/space/image_space_fs.h
+++ b/runtime/gc/space/image_space_fs.h
@@ -23,13 +23,13 @@
 #include "android-base/stringprintf.h"
 
 #include "base/file_utils.h"
-#include "base/globals.h"
 #include "base/logging.h"  // For VLOG.
 #include "base/macros.h"
 #include "base/os.h"
 #include "base/unix_file/fd_file.h"
 #include "base/utils.h"
 #include "runtime.h"
+#include "runtime_globals.h"
 
 namespace art {
 namespace gc {
diff --git a/runtime/gc/space/malloc_space.cc b/runtime/gc/space/malloc_space.cc
index b5e6b62..474231b 100644
--- a/runtime/gc/space/malloc_space.cc
+++ b/runtime/gc/space/malloc_space.cc
@@ -16,6 +16,8 @@
 
 #include "malloc_space.h"
 
+#include <ostream>
+
 #include "android-base/stringprintf.h"
 
 #include "base/logging.h"  // For VLOG
diff --git a/runtime/gc/space/malloc_space.h b/runtime/gc/space/malloc_space.h
index 7d28516..9a90dfd 100644
--- a/runtime/gc/space/malloc_space.h
+++ b/runtime/gc/space/malloc_space.h
@@ -19,7 +19,8 @@
 
 #include "space.h"
 
-#include <ostream>
+#include <iosfwd>
+
 #include "base/memory_tool.h"
 #include "base/mutex.h"
 
diff --git a/runtime/gc/space/space.h b/runtime/gc/space/space.h
index dd5451b..903263f 100644
--- a/runtime/gc/space/space.h
+++ b/runtime/gc/space/space.h
@@ -21,12 +21,12 @@
 #include <string>
 
 #include "base/atomic.h"
-#include "base/globals.h"
 #include "base/locks.h"
 #include "base/macros.h"
 #include "base/mem_map.h"
 #include "gc/accounting/space_bitmap.h"
 #include "gc/collector/object_byte_pair.h"
+#include "runtime_globals.h"
 
 namespace art {
 namespace mirror {
diff --git a/runtime/gc/space/space_test.h b/runtime/gc/space/space_test.h
index 1b111e3..7fbd0b5 100644
--- a/runtime/gc/space/space_test.h
+++ b/runtime/gc/space/space_test.h
@@ -20,13 +20,13 @@
 #include <stdint.h>
 #include <memory>
 
-#include "base/globals.h"
 #include "common_runtime_test.h"
 #include "handle_scope-inl.h"
 #include "mirror/array-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
 #include "mirror/object-inl.h"
+#include "runtime_globals.h"
 #include "scoped_thread_state_change-inl.h"
 #include "thread_list.h"
 #include "zygote_space.h"
diff --git a/runtime/gc/task_processor.h b/runtime/gc/task_processor.h
index 6db3c37..86e36ab 100644
--- a/runtime/gc/task_processor.h
+++ b/runtime/gc/task_processor.h
@@ -20,8 +20,8 @@
 #include <memory>
 #include <set>
 
-#include "base/globals.h"
 #include "base/mutex.h"
+#include "runtime_globals.h"
 #include "thread_pool.h"
 
 namespace art {
diff --git a/runtime/handle_scope-inl.h b/runtime/handle_scope-inl.h
index f61c700..765ed7d 100644
--- a/runtime/handle_scope-inl.h
+++ b/runtime/handle_scope-inl.h
@@ -21,6 +21,7 @@
 
 #include "base/mutex.h"
 #include "handle.h"
+#include "handle_wrapper.h"
 #include "obj_ptr-inl.h"
 #include "thread-current-inl.h"
 #include "verify_object.h"
@@ -106,6 +107,15 @@
       handle_scope_entry <= &GetReferences()[number_of_references_ - 1];
 }
 
+template <typename Visitor>
+inline void HandleScope::VisitRoots(Visitor& visitor) {
+  for (size_t i = 0, count = NumberOfReferences(); i < count; ++i) {
+    // GetReference returns a pointer to the stack reference within the handle scope. If this
+    // needs to be updated, it will be done by the root visitor.
+    visitor.VisitRootIfNonNull(GetHandle(i).GetReference());
+  }
+}
+
 template<size_t kNumReferences> template<class T>
 inline MutableHandle<T> FixedSizeHandleScope<kNumReferences>::NewHandle(T* object) {
   SetReference(pos_, object);
diff --git a/runtime/handle_scope.h b/runtime/handle_scope.h
index 6667aa3..ec1d166 100644
--- a/runtime/handle_scope.h
+++ b/runtime/handle_scope.h
@@ -24,13 +24,16 @@
 #include "base/enums.h"
 #include "base/locks.h"
 #include "base/macros.h"
-#include "handle.h"
 #include "stack_reference.h"
 #include "verify_object.h"
 
 namespace art {
 
+template<class T> class Handle;
 class HandleScope;
+template<class T> class HandleWrapper;
+template<class T> class HandleWrapperObjPtr;
+template<class T> class MutableHandle;
 template<class MirrorType> class ObjPtr;
 class Thread;
 class VariableSizedHandleScope;
@@ -144,13 +147,7 @@
   }
 
   template <typename Visitor>
-  void VisitRoots(Visitor& visitor) REQUIRES_SHARED(Locks::mutator_lock_) {
-    for (size_t i = 0, count = NumberOfReferences(); i < count; ++i) {
-      // GetReference returns a pointer to the stack reference within the handle scope. If this
-      // needs to be updated, it will be done by the root visitor.
-      visitor.VisitRootIfNonNull(GetHandle(i).GetReference());
-    }
-  }
+  ALWAYS_INLINE void VisitRoots(Visitor& visitor) REQUIRES_SHARED(Locks::mutator_lock_);
 
  protected:
   // Return backing storage used for references.
@@ -172,44 +169,6 @@
   DISALLOW_COPY_AND_ASSIGN(HandleScope);
 };
 
-// A wrapper which wraps around Object** and restores the pointer in the destructor.
-// TODO: Delete
-template<class T>
-class HandleWrapper : public MutableHandle<T> {
- public:
-  HandleWrapper(T** obj, const MutableHandle<T>& handle)
-     : MutableHandle<T>(handle), obj_(obj) {
-  }
-
-  HandleWrapper(const HandleWrapper&) = default;
-
-  ~HandleWrapper() {
-    *obj_ = MutableHandle<T>::Get();
-  }
-
- private:
-  T** const obj_;
-};
-
-
-// A wrapper which wraps around ObjPtr<Object>* and restores the pointer in the destructor.
-// TODO: Add more functionality.
-template<class T>
-class HandleWrapperObjPtr : public MutableHandle<T> {
- public:
-  HandleWrapperObjPtr(ObjPtr<T>* obj, const MutableHandle<T>& handle)
-      : MutableHandle<T>(handle), obj_(obj) {}
-
-  HandleWrapperObjPtr(const HandleWrapperObjPtr&) = default;
-
-  ~HandleWrapperObjPtr() {
-    *obj_ = ObjPtr<T>(MutableHandle<T>::Get());
-  }
-
- private:
-  ObjPtr<T>* const obj_;
-};
-
 // Fixed size handle scope that is not necessarily linked in the thread.
 template<size_t kNumReferences>
 class PACKED(4) FixedSizeHandleScope : public HandleScope {
diff --git a/runtime/handle_wrapper.h b/runtime/handle_wrapper.h
new file mode 100644
index 0000000..01252c7
--- /dev/null
+++ b/runtime/handle_wrapper.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2014 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_HANDLE_WRAPPER_H_
+#define ART_RUNTIME_HANDLE_WRAPPER_H_
+
+#include "handle.h"
+#include "obj_ptr.h"
+
+namespace art {
+
+// A wrapper which wraps around Object** and restores the pointer in the destructor.
+// TODO: Delete
+template<class T>
+class HandleWrapper : public MutableHandle<T> {
+ public:
+  HandleWrapper(T** obj, const MutableHandle<T>& handle)
+     : MutableHandle<T>(handle), obj_(obj) {
+  }
+
+  HandleWrapper(const HandleWrapper&) = default;
+
+  ~HandleWrapper() {
+    *obj_ = MutableHandle<T>::Get();
+  }
+
+ private:
+  T** const obj_;
+};
+
+
+// A wrapper which wraps around ObjPtr<Object>* and restores the pointer in the destructor.
+// TODO: Add more functionality.
+template<class T>
+class HandleWrapperObjPtr : public MutableHandle<T> {
+ public:
+  HandleWrapperObjPtr(ObjPtr<T>* obj, const MutableHandle<T>& handle)
+      : MutableHandle<T>(handle), obj_(obj) {}
+
+  HandleWrapperObjPtr(const HandleWrapperObjPtr&) = default;
+
+  ~HandleWrapperObjPtr() {
+    *obj_ = ObjPtr<T>(MutableHandle<T>::Get());
+  }
+
+ private:
+  ObjPtr<T>* const obj_;
+};
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_HANDLE_WRAPPER_H_
diff --git a/runtime/hidden_api.cc b/runtime/hidden_api.cc
index c146daa..2d3493d 100644
--- a/runtime/hidden_api.cc
+++ b/runtime/hidden_api.cc
@@ -361,9 +361,11 @@
                                   hiddenapi::ApiList api_list,
                                   AccessMethod access_method) {
   DCHECK(member != nullptr);
-
   Runtime* runtime = Runtime::Current();
+
   EnforcementPolicy policy = runtime->GetHiddenApiEnforcementPolicy();
+  DCHECK(policy != EnforcementPolicy::kDisabled)
+      << "Should never enter this function when access checks are completely disabled";
 
   const bool deny_access =
       (policy == EnforcementPolicy::kEnabled) &&
diff --git a/runtime/hidden_api.h b/runtime/hidden_api.h
index a0eeae2..1a5e010 100644
--- a/runtime/hidden_api.h
+++ b/runtime/hidden_api.h
@@ -311,6 +311,11 @@
     return false;
   }
 
+  // Exit early if access checks are completely disabled.
+  if (Runtime::Current()->GetHiddenApiEnforcementPolicy() == EnforcementPolicy::kDisabled) {
+    return false;
+  }
+
   // Check if caller is exempted from access checks.
   // This can be *very* expensive. Save it for last.
   if (fn_get_access_context().IsTrusted()) {
diff --git a/runtime/hidden_api_test.cc b/runtime/hidden_api_test.cc
index 595f077..1f83c05 100644
--- a/runtime/hidden_api_test.cc
+++ b/runtime/hidden_api_test.cc
@@ -100,13 +100,6 @@
 TEST_F(HiddenApiTest, CheckGetActionFromRuntimeFlags) {
   ScopedObjectAccess soa(self_);
 
-  runtime_->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kDisabled);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Whitelist()), false);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Greylist()), false);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxP()), false);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxO()), false);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Blacklist()), false);
-
   runtime_->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kJustWarn);
   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Whitelist()), false);
   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Greylist()), false);
diff --git a/runtime/hprof/hprof.cc b/runtime/hprof/hprof.cc
index 3abe4c5..34f645b 100644
--- a/runtime/hprof/hprof.cc
+++ b/runtime/hprof/hprof.cc
@@ -42,7 +42,6 @@
 #include "art_method-inl.h"
 #include "base/array_ref.h"
 #include "base/file_utils.h"
-#include "base/globals.h"
 #include "base/macros.h"
 #include "base/mutex.h"
 #include "base/os.h"
@@ -66,6 +65,7 @@
 #include "mirror/class-inl.h"
 #include "mirror/class.h"
 #include "mirror/object-refvisitor-inl.h"
+#include "runtime_globals.h"
 #include "scoped_thread_state_change-inl.h"
 #include "thread_list.h"
 
diff --git a/runtime/image.h b/runtime/image.h
index 140f504..6578287 100644
--- a/runtime/image.h
+++ b/runtime/image.h
@@ -20,9 +20,9 @@
 #include <string.h>
 
 #include "base/enums.h"
-#include "base/globals.h"
 #include "base/iteration_range.h"
 #include "mirror/object.h"
+#include "runtime_globals.h"
 
 namespace art {
 
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index 27c47bc..36f7b3d 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -848,7 +848,7 @@
         new_quick_code = GetQuickInstrumentationEntryPoint();
         if (!method->IsNative() && Runtime::Current()->GetJit() != nullptr) {
           // Native methods use trampoline entrypoints during interpreter tracing.
-          DCHECK(!Runtime::Current()->GetJit()->GetCodeCache()->GetGarbageCollectCode());
+          DCHECK(!Runtime::Current()->GetJit()->GetCodeCache()->GetGarbageCollectCodeUnsafe());
           ProfilingInfo* profiling_info = method->GetProfilingInfo(kRuntimePointerSize);
           // Tracing will look at the saved entry point in the profiling info to know the actual
           // entrypoint, so we store it here.
@@ -1050,14 +1050,6 @@
     level = InstrumentationLevel::kInstrumentWithInterpreter;
   } else {
     level = InstrumentationLevel::kInstrumentWithInstrumentationStubs;
-    if (Runtime::Current()->GetJit() != nullptr) {
-      // TODO b/110263880 It would be better if we didn't need to do this.
-      // Since we need to hold the method entrypoint across a suspend to ensure instrumentation
-      // hooks are called correctly we have to disable jit-gc to ensure that the entrypoint doesn't
-      // go away. Furthermore we need to leave this off permanently since one could get the same
-      // effect by causing this to be toggled on and off.
-      Runtime::Current()->GetJit()->GetCodeCache()->SetGarbageCollectCode(false);
-    }
   }
   ConfigureStubs(key, level);
 }
diff --git a/runtime/jdwp_provider.h b/runtime/jdwp_provider.h
index 9579513..29fbc3f 100644
--- a/runtime/jdwp_provider.h
+++ b/runtime/jdwp_provider.h
@@ -19,7 +19,7 @@
 
 #include <ios>
 
-#include "base/globals.h"
+#include "runtime_globals.h"
 
 namespace art {
 
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index d976fec..c1b9a1a 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -390,7 +390,7 @@
 
   // Zygote should never collect code to share the memory with the children.
   if (is_zygote) {
-    jit_code_cache->SetGarbageCollectCode(false);
+    jit_code_cache->garbage_collect_code_ = false;
   }
 
   if (!jit_code_cache->InitializeMappings(rwx_memory_allowed, is_zygote, error_msg)) {
@@ -1247,6 +1247,24 @@
   }
 }
 
+void JitCodeCache::ClearEntryPointsInZygoteExecSpace() {
+  MutexLock mu(Thread::Current(), lock_);
+  // Iterate over profiling infos to know which methods may have been JITted. Note that
+  // to be JITted, a method must have a profiling info.
+  for (ProfilingInfo* info : profiling_infos_) {
+    ArtMethod* method = info->GetMethod();
+    if (IsInZygoteExecSpace(method->GetEntryPointFromQuickCompiledCode())) {
+      method->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
+    }
+    // If zygote does method tracing, or in some configuration where
+    // the JIT zygote does GC, we also need to clear the saved entry point
+    // in the profiling info.
+    if (IsInZygoteExecSpace(info->GetSavedEntryPoint())) {
+      info->SetSavedEntryPoint(nullptr);
+    }
+  }
+}
+
 size_t JitCodeCache::CodeCacheSizeLocked() {
   return used_memory_for_code_;
 }
@@ -1437,17 +1455,14 @@
 
 void JitCodeCache::GarbageCollectCache(Thread* self) {
   ScopedTrace trace(__FUNCTION__);
-  if (!garbage_collect_code_) {
-    MutexLock mu(self, lock_);
-    IncreaseCodeCacheCapacity();
-    return;
-  }
-
   // Wait for an existing collection, or let everyone know we are starting one.
   {
     ScopedThreadSuspension sts(self, kSuspended);
     MutexLock mu(self, lock_);
-    if (WaitForPotentialCollectionToComplete(self)) {
+    if (!garbage_collect_code_) {
+      IncreaseCodeCacheCapacity();
+      return;
+    } else if (WaitForPotentialCollectionToComplete(self)) {
       return;
     } else {
       number_of_collections_++;
@@ -1573,6 +1588,29 @@
   FreeAllMethodHeaders(method_headers);
 }
 
+bool JitCodeCache::GetGarbageCollectCode() {
+  MutexLock mu(Thread::Current(), lock_);
+  return garbage_collect_code_;
+}
+
+void JitCodeCache::SetGarbageCollectCode(bool value) {
+  Thread* self = Thread::Current();
+  MutexLock mu(self, lock_);
+  if (garbage_collect_code_ != value) {
+    if (garbage_collect_code_) {
+      // When dynamically disabling the garbage collection, we neee
+      // to make sure that a potential current collection is finished, and also
+      // clear the saved entry point in profiling infos to avoid dangling pointers.
+      WaitForPotentialCollectionToComplete(self);
+      for (ProfilingInfo* info : profiling_infos_) {
+        info->SetSavedEntryPoint(nullptr);
+      }
+    }
+    // Update the flag while holding the lock to ensure no thread will try to GC.
+    garbage_collect_code_ = value;
+  }
+}
+
 void JitCodeCache::DoCollection(Thread* self, bool collect_profiling_info) {
   ScopedTrace trace(__FUNCTION__);
   {
diff --git a/runtime/jit/jit_code_cache.h b/runtime/jit/jit_code_cache.h
index e2f3357..8a6cebe 100644
--- a/runtime/jit/jit_code_cache.h
+++ b/runtime/jit/jit_code_cache.h
@@ -246,13 +246,13 @@
   void MoveObsoleteMethod(ArtMethod* old_method, ArtMethod* new_method)
       REQUIRES(!lock_) REQUIRES(Locks::mutator_lock_);
 
-  // Dynamically change whether we want to garbage collect code. Should only be used during JIT
-  // initialization or by tests.
-  void SetGarbageCollectCode(bool value) {
-    garbage_collect_code_ = value;
-  }
+  // Dynamically change whether we want to garbage collect code.
+  void SetGarbageCollectCode(bool value) REQUIRES(!lock_);
 
-  bool GetGarbageCollectCode() const {
+  bool GetGarbageCollectCode() REQUIRES(!lock_);
+
+  // Unsafe variant for debug checks.
+  bool GetGarbageCollectCodeUnsafe() const NO_THREAD_SAFETY_ANALYSIS {
     return garbage_collect_code_;
   }
 
@@ -264,6 +264,11 @@
 
   void PostForkChildAction(bool is_system_server, bool is_zygote);
 
+  // Clear the entrypoints of JIT compiled methods that belong in the zygote space.
+  // This is used for removing non-debuggable JIT code at the point we realize the runtime
+  // is debuggable.
+  void ClearEntryPointsInZygoteExecSpace() REQUIRES(!lock_) REQUIRES(Locks::mutator_lock_);
+
  private:
   JitCodeCache();
 
@@ -451,7 +456,7 @@
   bool last_collection_increased_code_cache_ GUARDED_BY(lock_);
 
   // Whether we can do garbage collection. Not 'const' as tests may override this.
-  bool garbage_collect_code_;
+  bool garbage_collect_code_ GUARDED_BY(lock_);
 
   // The size in bytes of used memory for the data portion of the code cache.
   size_t used_memory_for_data_ GUARDED_BY(lock_);
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 40c7d30..fe49813 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -39,6 +39,7 @@
 #include "runtime.h"
 #include "string.h"
 #include "subtype_check.h"
+#include "thread-current-inl.h"
 
 namespace art {
 namespace mirror {
@@ -1117,6 +1118,18 @@
   }
 }
 
+inline void Class::SetRecursivelyInitialized() {
+  DCHECK_EQ(GetLockOwnerThreadId(), Thread::Current()->GetThreadId());
+  uint32_t flags = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_));
+  SetAccessFlags(flags | kAccRecursivelyInitialized);
+}
+
+inline void Class::SetHasDefaultMethods() {
+  DCHECK_EQ(GetLockOwnerThreadId(), Thread::Current()->GetThreadId());
+  uint32_t flags = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_));
+  SetAccessFlags(flags | kAccHasDefaultMethod);
+}
+
 }  // namespace mirror
 }  // namespace art
 
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index f7a41f7..d35d526 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -30,7 +30,6 @@
 #include "object.h"
 #include "object_array.h"
 #include "read_barrier_option.h"
-#include "thread-current-inl.h"
 
 namespace art {
 
@@ -52,6 +51,7 @@
 class Signature;
 class StringPiece;
 template<size_t kNumReferences> class PACKED(4) StackHandleScope;
+class Thread;
 
 namespace mirror {
 
@@ -223,17 +223,9 @@
     SetAccessFlags(flags | kAccSkipHiddenapiChecks);
   }
 
-  ALWAYS_INLINE void SetRecursivelyInitialized() REQUIRES_SHARED(Locks::mutator_lock_) {
-    DCHECK_EQ(GetLockOwnerThreadId(), Thread::Current()->GetThreadId());
-    uint32_t flags = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_));
-    SetAccessFlags(flags | kAccRecursivelyInitialized);
-  }
+  ALWAYS_INLINE void SetRecursivelyInitialized() REQUIRES_SHARED(Locks::mutator_lock_);
 
-  ALWAYS_INLINE void SetHasDefaultMethods() REQUIRES_SHARED(Locks::mutator_lock_) {
-    DCHECK_EQ(GetLockOwnerThreadId(), Thread::Current()->GetThreadId());
-    uint32_t flags = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_));
-    SetAccessFlags(flags | kAccHasDefaultMethod);
-  }
+  ALWAYS_INLINE void SetHasDefaultMethods() REQUIRES_SHARED(Locks::mutator_lock_);
 
   ALWAYS_INLINE void SetFinalizable() REQUIRES_SHARED(Locks::mutator_lock_) {
     uint32_t flags = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_));
diff --git a/runtime/mirror/dex_cache.cc b/runtime/mirror/dex_cache.cc
index 8d2b838..7e79ebe 100644
--- a/runtime/mirror/dex_cache.cc
+++ b/runtime/mirror/dex_cache.cc
@@ -17,7 +17,6 @@
 #include "dex_cache-inl.h"
 
 #include "art_method-inl.h"
-#include "base/globals.h"
 #include "class_linker.h"
 #include "gc/accounting/card_table-inl.h"
 #include "gc/heap.h"
@@ -27,6 +26,7 @@
 #include "object.h"
 #include "object_array-inl.h"
 #include "runtime.h"
+#include "runtime_globals.h"
 #include "string.h"
 #include "thread.h"
 #include "utils/dex_cache_arrays_layout-inl.h"
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index bca7511..ba222f6 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -20,13 +20,13 @@
 #include "base/atomic.h"
 #include "base/casts.h"
 #include "base/enums.h"
-#include "base/globals.h"
 #include "dex/primitive.h"
 #include "obj_ptr.h"
 #include "object_reference.h"
 #include "offsets.h"
 #include "read_barrier_config.h"
 #include "read_barrier_option.h"
+#include "runtime_globals.h"
 #include "verify_object.h"
 
 namespace art {
diff --git a/runtime/mirror/object_reference.h b/runtime/mirror/object_reference.h
index 8636928..e19e165 100644
--- a/runtime/mirror/object_reference.h
+++ b/runtime/mirror/object_reference.h
@@ -18,10 +18,10 @@
 #define ART_RUNTIME_MIRROR_OBJECT_REFERENCE_H_
 
 #include "base/atomic.h"
-#include "base/globals.h"
 #include "base/locks.h"  // For Locks::mutator_lock_.
 #include "heap_poisoning.h"
 #include "obj_ptr.h"
+#include "runtime_globals.h"
 
 namespace art {
 namespace mirror {
diff --git a/runtime/mirror/string-alloc-inl.h b/runtime/mirror/string-alloc-inl.h
index c31eccf..4c4e2af 100644
--- a/runtime/mirror/string-alloc-inl.h
+++ b/runtime/mirror/string-alloc-inl.h
@@ -22,11 +22,11 @@
 
 #include "array.h"
 #include "base/bit_utils.h"
-#include "base/globals.h"
 #include "class.h"
 #include "class_root.h"
 #include "gc/heap-inl.h"
 #include "runtime.h"
+#include "runtime_globals.h"
 #include "thread.h"
 
 namespace art {
diff --git a/runtime/mirror/string-inl.h b/runtime/mirror/string-inl.h
index e11906a..f04a8aa 100644
--- a/runtime/mirror/string-inl.h
+++ b/runtime/mirror/string-inl.h
@@ -20,10 +20,10 @@
 
 #include "android-base/stringprintf.h"
 
-#include "base/globals.h"
 #include "class-inl.h"
 #include "common_throws.h"
 #include "dex/utf.h"
+#include "runtime_globals.h"
 
 namespace art {
 namespace mirror {
diff --git a/runtime/mirror/string.h b/runtime/mirror/string.h
index b32db08..c367957 100644
--- a/runtime/mirror/string.h
+++ b/runtime/mirror/string.h
@@ -18,10 +18,10 @@
 #define ART_RUNTIME_MIRROR_STRING_H_
 
 #include "base/bit_utils.h"
-#include "base/globals.h"
 #include "gc/allocator_type.h"
 #include "class.h"
 #include "object.h"
+#include "runtime_globals.h"
 
 namespace art {
 
diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index 9ce4749..26fc5e9 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -203,8 +203,11 @@
     runtime->AddCompilerOption("--debuggable");
     runtime_flags |= DEBUG_GENERATE_MINI_DEBUG_INFO;
     runtime->SetJavaDebuggable(true);
-    // Deoptimize the boot image as it may be non-debuggable.
-    runtime->DeoptimizeBootImage();
+    {
+      // Deoptimize the boot image as it may be non-debuggable.
+      ScopedSuspendAll ssa(__FUNCTION__);
+      runtime->DeoptimizeBootImage();
+    }
     runtime_flags &= ~DEBUG_JAVA_DEBUGGABLE;
     needs_non_debuggable_classes = true;
   }
diff --git a/runtime/oat.cc b/runtime/oat.cc
index d7c968f..c6a963a 100644
--- a/runtime/oat.cc
+++ b/runtime/oat.cc
@@ -20,6 +20,7 @@
 
 #include "android-base/stringprintf.h"
 
+#include "arch/instruction_set.h"
 #include "arch/instruction_set_features.h"
 #include "base/bit_utils.h"
 #include "base/strlcpy.h"
diff --git a/runtime/oat.h b/runtime/oat.h
index ded1489..88238d9 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -19,13 +19,13 @@
 
 #include <vector>
 
-#include "arch/instruction_set.h"
 #include "base/macros.h"
 #include "base/safe_map.h"
 #include "compiler_filter.h"
 
 namespace art {
 
+enum class InstructionSet;
 class InstructionSetFeatures;
 
 class PACKED(4) OatHeader {
diff --git a/runtime/obj_ptr-inl.h b/runtime/obj_ptr-inl.h
index b949c96..f096445 100644
--- a/runtime/obj_ptr-inl.h
+++ b/runtime/obj_ptr-inl.h
@@ -17,6 +17,8 @@
 #ifndef ART_RUNTIME_OBJ_PTR_INL_H_
 #define ART_RUNTIME_OBJ_PTR_INL_H_
 
+#include <ostream>
+
 #include "base/bit_utils.h"
 #include "obj_ptr.h"
 #include "thread-current-inl.h"
diff --git a/runtime/obj_ptr.h b/runtime/obj_ptr.h
index 9e2ee29..b0f24da 100644
--- a/runtime/obj_ptr.h
+++ b/runtime/obj_ptr.h
@@ -17,12 +17,12 @@
 #ifndef ART_RUNTIME_OBJ_PTR_H_
 #define ART_RUNTIME_OBJ_PTR_H_
 
-#include <ostream>
+#include <iosfwd>
 #include <type_traits>
 
-#include "base/globals.h"
 #include "base/locks.h"  // For Locks::mutator_lock_.
 #include "base/macros.h"
+#include "runtime_globals.h"
 
 // Always inline ObjPtr methods even in debug builds.
 #define OBJPTR_INLINE __attribute__ ((always_inline))
diff --git a/runtime/offsets.h b/runtime/offsets.h
index 372b821..6d1a8e0 100644
--- a/runtime/offsets.h
+++ b/runtime/offsets.h
@@ -17,10 +17,10 @@
 #ifndef ART_RUNTIME_OFFSETS_H_
 #define ART_RUNTIME_OFFSETS_H_
 
-#include <ostream>
+#include <iosfwd>
 
 #include "base/enums.h"
-#include "base/globals.h"
+#include "runtime_globals.h"
 
 namespace art {
 
diff --git a/runtime/parsed_options.h b/runtime/parsed_options.h
index 8c77d39..095d66e 100644
--- a/runtime/parsed_options.h
+++ b/runtime/parsed_options.h
@@ -23,10 +23,10 @@
 #include <jni.h>
 
 #include "arch/instruction_set.h"
-#include "base/globals.h"
 #include "gc/collector_type.h"
 #include "gc/space/large_object_space.h"
 // #include "jit/profile_saver_options.h"
+#include "runtime_globals.h"
 #include "runtime_options.h"
 
 namespace art {
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index 0d570c3..3bc718b 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -20,6 +20,7 @@
 #include "art_method-inl.h"
 #include "base/enums.h"
 #include "base/logging.h"  // For VLOG_IS_ON.
+#include "base/systrace.h"
 #include "dex/dex_file_types.h"
 #include "dex/dex_instruction.h"
 #include "entrypoints/entrypoint_utils.h"
@@ -592,6 +593,10 @@
 
   // Compiled code made an explicit deoptimization.
   ArtMethod* deopt_method = visitor.GetSingleFrameDeoptMethod();
+  SCOPED_TRACE << "Deoptimizing "
+               <<  deopt_method->PrettyMethod()
+               << ": " << GetDeoptimizationKindName(kind);
+
   DCHECK(deopt_method != nullptr);
   if (VLOG_IS_ON(deopt) || kDebugExceptionDelivery) {
     LOG(INFO) << "Single-frame deopting: "
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index dfd7e64..dbf40f6 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -33,6 +33,7 @@
 #include "nth_caller_visitor.h"
 #include "scoped_thread_state_change-inl.h"
 #include "stack_reference.h"
+#include "thread-inl.h"
 #include "well_known_classes.h"
 
 namespace art {
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index f30ba0c..d79793b 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -42,6 +42,7 @@
 #include "aot_class_linker.h"
 #include "arch/arm/registers_arm.h"
 #include "arch/arm64/registers_arm64.h"
+#include "arch/context.h"
 #include "arch/instruction_set_features.h"
 #include "arch/mips/registers_mips.h"
 #include "arch/mips64/registers_mips64.h"
@@ -323,7 +324,6 @@
 
   if (dump_gc_performance_on_shutdown_) {
     heap_->CalculatePreGcWeightedAllocatedBytes();
-    heap_->CalculatePostGcWeightedAllocatedBytes();
     uint64_t process_cpu_end_time = ProcessCpuNanoTime();
     ScopedLogSeverity sls(LogSeverity::INFO);
     // This can't be called from the Heap destructor below because it
@@ -340,8 +340,12 @@
         << "\n";
     double pre_gc_weighted_allocated_bytes =
         heap_->GetPreGcWeightedAllocatedBytes() / process_cpu_time;
+    // Here we don't use process_cpu_time for normalization, because VM shutdown is not a real
+    // GC. Both numerator and denominator take into account until the end of the last GC,
+    // instead of the whole process life time like pre_gc_weighted_allocated_bytes.
     double post_gc_weighted_allocated_bytes =
-        heap_->GetPostGcWeightedAllocatedBytes() / process_cpu_time;
+        heap_->GetPostGcWeightedAllocatedBytes() /
+          (heap_->GetPostGCLastProcessCpuTime() - heap_->GetProcessCpuStartTime());
 
     LOG_STREAM(INFO) << "Average bytes allocated at GC start, weighted by CPU time between GCs: "
         << static_cast<uint64_t>(pre_gc_weighted_allocated_bytes)
@@ -1472,6 +1476,8 @@
     if (IsJavaDebuggable()) {
       // Now that we have loaded the boot image, deoptimize its methods if we are running
       // debuggable, as the code may have been compiled non-debuggable.
+      ScopedThreadSuspension sts(self, ThreadState::kNative);
+      ScopedSuspendAll ssa(__FUNCTION__);
       DeoptimizeBootImage();
     }
   } else {
@@ -1571,10 +1577,14 @@
   // Runtime initialization is largely done now.
   // We load plugins first since that can modify the runtime state slightly.
   // Load all plugins
-  for (auto& plugin : plugins_) {
-    std::string err;
-    if (!plugin.Load(&err)) {
-      LOG(FATAL) << plugin << " failed to load: " << err;
+  {
+    // The init method of plugins expect the state of the thread to be non runnable.
+    ScopedThreadSuspension sts(self, ThreadState::kNative);
+    for (auto& plugin : plugins_) {
+      std::string err;
+      if (!plugin.Load(&err)) {
+        LOG(FATAL) << plugin << " failed to load: " << err;
+      }
     }
   }
 
@@ -2647,6 +2657,7 @@
       : instrumentation_(instrumentation) {}
 
   bool operator()(ObjPtr<mirror::Class> klass) override REQUIRES(Locks::mutator_lock_) {
+    DCHECK(Locks::mutator_lock_->IsExclusiveHeld(Thread::Current()));
     auto pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
     for (auto& m : klass->GetMethods(pointer_size)) {
       const void* code = m.GetEntryPointFromQuickCompiledCode();
@@ -2673,9 +2684,13 @@
   // we patch entry points of methods in boot image to interpreter bridge, as
   // boot image code may be AOT compiled as not debuggable.
   if (!GetInstrumentation()->IsForcedInterpretOnly()) {
-    ScopedObjectAccess soa(Thread::Current());
     UpdateEntryPointsClassVisitor visitor(GetInstrumentation());
     GetClassLinker()->VisitClasses(&visitor);
+    jit::Jit* jit = GetJit();
+    if (jit != nullptr) {
+      // Code JITted by the zygote is not compiled debuggable.
+      jit->GetCodeCache()->ClearEntryPointsInZygoteExecSpace();
+    }
   }
 }
 
diff --git a/runtime/runtime.h b/runtime/runtime.h
index a2d519d..1acb75b 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -27,7 +27,6 @@
 #include <memory>
 #include <vector>
 
-#include "arch/instruction_set.h"
 #include "base/locks.h"
 #include "base/macros.h"
 #include "base/mem_map.h"
@@ -84,6 +83,7 @@
 class ClassLinker;
 class CompilerCallbacks;
 class DexFile;
+enum class InstructionSet;
 class InternTable;
 class IsMarkedVisitor;
 class JavaVMExt;
@@ -634,7 +634,7 @@
   void SetJavaDebuggable(bool value);
 
   // Deoptimize the boot image, called for Java debuggable apps.
-  void DeoptimizeBootImage();
+  void DeoptimizeBootImage() REQUIRES(Locks::mutator_lock_);
 
   bool IsNativeDebuggable() const {
     return is_native_debuggable_;
diff --git a/runtime/runtime_globals.h b/runtime/runtime_globals.h
new file mode 100644
index 0000000..793291a
--- /dev/null
+++ b/runtime/runtime_globals.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2011 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_RUNTIME_GLOBALS_H_
+#define ART_RUNTIME_RUNTIME_GLOBALS_H_
+
+#include "base/globals.h"
+
+namespace art {
+
+// Size of Dex virtual registers.
+static constexpr size_t kVRegSize = 4;
+
+// Returns whether the given memory offset can be used for generating
+// an implicit null check.
+static inline bool CanDoImplicitNullCheckOn(uintptr_t offset) {
+  return offset < kPageSize;
+}
+
+// Required object alignment
+static constexpr size_t kObjectAlignmentShift = 3;
+static constexpr size_t kObjectAlignment = 1u << kObjectAlignmentShift;
+static constexpr size_t kLargeObjectAlignment = kPageSize;
+
+// Garbage collector constants.
+static constexpr bool kMovingCollector = true;
+static constexpr bool kMarkCompactSupport = false && kMovingCollector;
+// True if we allow moving classes.
+static constexpr bool kMovingClasses = !kMarkCompactSupport;
+// If true, enable generational collection when using the Concurrent Copying
+// (CC) collector, i.e. use sticky-bit CC for minor collections and (full) CC
+// for major collections.
+//
+// Generational CC collection is currently only compatible with Baker read
+// barriers.
+#if defined(ART_USE_GENERATIONAL_CC) && defined(ART_READ_BARRIER_TYPE_IS_BAKER)
+static constexpr bool kEnableGenerationalConcurrentCopyingCollection = true;
+#else
+static constexpr bool kEnableGenerationalConcurrentCopyingCollection = false;
+#endif
+
+// If true, enable the tlab allocator by default.
+#ifdef ART_USE_TLAB
+static constexpr bool kUseTlab = true;
+#else
+static constexpr bool kUseTlab = false;
+#endif
+
+// Kinds of tracing clocks.
+enum class TraceClockSource {
+  kThreadCpu,
+  kWall,
+  kDual,  // Both wall and thread CPU clocks.
+};
+
+#if defined(__linux__)
+static constexpr TraceClockSource kDefaultTraceClockSource = TraceClockSource::kDual;
+#else
+static constexpr TraceClockSource kDefaultTraceClockSource = TraceClockSource::kWall;
+#endif
+
+static constexpr bool kDefaultMustRelocate = true;
+
+// Size of a heap reference.
+static constexpr size_t kHeapReferenceSize = sizeof(uint32_t);
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_RUNTIME_GLOBALS_H_
diff --git a/runtime/stack.cc b/runtime/stack.cc
index 25939d2..9a677de 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -568,7 +568,9 @@
     cur_shadow_frame_->SetMethod(method);
   } else {
     DCHECK(cur_quick_frame_ != nullptr);
-    CHECK(!IsInInlinedFrame()) << "We do not support setting inlined method's ArtMethod!";
+    CHECK(!IsInInlinedFrame()) << "We do not support setting inlined method's ArtMethod: "
+                               << GetMethod()->PrettyMethod() << " is inlined into "
+                               << GetOuterMethod()->PrettyMethod();
     *cur_quick_frame_ = method;
   }
 }
diff --git a/runtime/suspend_reason.h b/runtime/suspend_reason.h
index 289a1a4..af2be10 100644
--- a/runtime/suspend_reason.h
+++ b/runtime/suspend_reason.h
@@ -17,7 +17,7 @@
 #ifndef ART_RUNTIME_SUSPEND_REASON_H_
 #define ART_RUNTIME_SUSPEND_REASON_H_
 
-#include <ostream>
+#include <iosfwd>
 
 namespace art {
 
diff --git a/runtime/thread-inl.h b/runtime/thread-inl.h
index 0c00fb9..00f882e 100644
--- a/runtime/thread-inl.h
+++ b/runtime/thread-inl.h
@@ -19,6 +19,7 @@
 
 #include "thread.h"
 
+#include "arch/instruction_set.h"
 #include "base/aborting.h"
 #include "base/casts.h"
 #include "base/mutex-inl.h"
@@ -393,6 +394,26 @@
   return tlsPtr_.managed_stack.PopShadowFrame();
 }
 
+inline uint8_t* Thread::GetStackEndForInterpreter(bool implicit_overflow_check) const {
+  uint8_t* end = tlsPtr_.stack_end + (implicit_overflow_check
+      ? GetStackOverflowReservedBytes(kRuntimeISA)
+          : 0);
+  if (kIsDebugBuild) {
+    // In a debuggable build, but especially under ASAN, the access-checks interpreter has a
+    // potentially humongous stack size. We don't want to take too much of the stack regularly,
+    // so do not increase the regular reserved size (for compiled code etc) and only report the
+    // virtually smaller stack to the interpreter here.
+    end += GetStackOverflowReservedBytes(kRuntimeISA);
+  }
+  return end;
+}
+
+inline void Thread::ResetDefaultStackEnd() {
+  // Our stacks grow down, so we want stack_end_ to be near there, but reserving enough room
+  // to throw a StackOverflowError.
+  tlsPtr_.stack_end = tlsPtr_.stack_begin + GetStackOverflowReservedBytes(kRuntimeISA);
+}
+
 }  // namespace art
 
 #endif  // ART_RUNTIME_THREAD_INL_H_
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 7c050a4..309c04e 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -48,6 +48,7 @@
 #include "base/atomic.h"
 #include "base/bit_utils.h"
 #include "base/casts.h"
+#include "arch/context.h"
 #include "base/file_utils.h"
 #include "base/memory_tool.h"
 #include "base/mutex.h"
@@ -4232,4 +4233,17 @@
   Runtime::Current()->GetThreadList()->RunCheckpoint(&closure);
 }
 
+void Thread::ReleaseLongJumpContextInternal() {
+  // Each QuickExceptionHandler gets a long jump context and uses
+  // it for doing the long jump, after finding catch blocks/doing deoptimization.
+  // Both finding catch blocks and deoptimization can trigger another
+  // exception such as a result of class loading. So there can be nested
+  // cases of exception handling and multiple contexts being used.
+  // ReleaseLongJumpContext tries to save the context in tlsPtr_.long_jump_context
+  // for reuse so there is no need to always allocate a new one each time when
+  // getting a context. Since we only keep one context for reuse, delete the
+  // existing one since the passed in context is yet to be used for longjump.
+  delete tlsPtr_.long_jump_context;
+}
+
 }  // namespace art
diff --git a/runtime/thread.h b/runtime/thread.h
index ad69ecf..7a14fd7 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -25,14 +25,12 @@
 #include <memory>
 #include <string>
 
-#include "arch/context.h"
-#include "arch/instruction_set.h"
 #include "base/atomic.h"
 #include "base/enums.h"
-#include "base/globals.h"
 #include "base/locks.h"
 #include "base/macros.h"
 #include "base/safe_map.h"
+#include "base/value_object.h"
 #include "entrypoints/jni/jni_entrypoints.h"
 #include "entrypoints/quick/quick_entrypoints.h"
 #include "handle_scope.h"
@@ -41,6 +39,7 @@
 #include "managed_stack.h"
 #include "offsets.h"
 #include "read_barrier_config.h"
+#include "runtime_globals.h"
 #include "runtime_stats.h"
 #include "suspend_reason.h"
 #include "thread_state.h"
@@ -471,16 +470,7 @@
   Context* GetLongJumpContext();
   void ReleaseLongJumpContext(Context* context) {
     if (tlsPtr_.long_jump_context != nullptr) {
-      // Each QuickExceptionHandler gets a long jump context and uses
-      // it for doing the long jump, after finding catch blocks/doing deoptimization.
-      // Both finding catch blocks and deoptimization can trigger another
-      // exception such as a result of class loading. So there can be nested
-      // cases of exception handling and multiple contexts being used.
-      // ReleaseLongJumpContext tries to save the context in tlsPtr_.long_jump_context
-      // for reuse so there is no need to always allocate a new one each time when
-      // getting a context. Since we only keep one context for reuse, delete the
-      // existing one since the passed in context is yet to be used for longjump.
-      delete tlsPtr_.long_jump_context;
+      ReleaseLongJumpContextInternal();
     }
     tlsPtr_.long_jump_context = context;
   }
@@ -819,19 +809,7 @@
     return tlsPtr_.stack_size - (tlsPtr_.stack_end - tlsPtr_.stack_begin);
   }
 
-  uint8_t* GetStackEndForInterpreter(bool implicit_overflow_check) const {
-    uint8_t* end = tlsPtr_.stack_end + (implicit_overflow_check
-                                            ? GetStackOverflowReservedBytes(kRuntimeISA)
-                                            : 0);
-    if (kIsDebugBuild) {
-      // In a debuggable build, but especially under ASAN, the access-checks interpreter has a
-      // potentially humongous stack size. We don't want to take too much of the stack regularly,
-      // so do not increase the regular reserved size (for compiled code etc) and only report the
-      // virtually smaller stack to the interpreter here.
-      end += GetStackOverflowReservedBytes(kRuntimeISA);
-    }
-    return end;
-  }
+  ALWAYS_INLINE uint8_t* GetStackEndForInterpreter(bool implicit_overflow_check) const;
 
   uint8_t* GetStackEnd() const {
     return tlsPtr_.stack_end;
@@ -841,11 +819,7 @@
   void SetStackEndForStackOverflow() REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Set the stack end to that to be used during regular execution
-  void ResetDefaultStackEnd() {
-    // Our stacks grow down, so we want stack_end_ to be near there, but reserving enough room
-    // to throw a StackOverflowError.
-    tlsPtr_.stack_end = tlsPtr_.stack_begin + GetStackOverflowReservedBytes(kRuntimeISA);
-  }
+  ALWAYS_INLINE void ResetDefaultStackEnd();
 
   bool IsHandlingStackOverflow() const {
     return tlsPtr_.stack_end == tlsPtr_.stack_begin;
@@ -1425,6 +1399,8 @@
 
   static bool IsAotCompiler();
 
+  void ReleaseLongJumpContextInternal();
+
   // 32 bits of atomically changed state and flags. Keeping as 32 bits allows and atomic CAS to
   // change from being Suspended to Runnable without a suspend request occurring.
   union PACKED(4) StateAndFlags {
diff --git a/runtime/thread_state.h b/runtime/thread_state.h
index 8edfeec..e57a040 100644
--- a/runtime/thread_state.h
+++ b/runtime/thread_state.h
@@ -17,7 +17,7 @@
 #ifndef ART_RUNTIME_THREAD_STATE_H_
 #define ART_RUNTIME_THREAD_STATE_H_
 
-#include <ostream>
+#include <iosfwd>
 
 namespace art {
 
diff --git a/runtime/trace.cc b/runtime/trace.cc
index ce955d8..074e846 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -38,6 +38,8 @@
 #include "entrypoints/quick/quick_entrypoints.h"
 #include "gc/scoped_gc_critical_section.h"
 #include "instrumentation.h"
+#include "jit/jit.h"
+#include "jit/jit_code_cache.h"
 #include "mirror/class-inl.h"
 #include "mirror/dex_cache-inl.h"
 #include "mirror/object-inl.h"
@@ -390,6 +392,15 @@
   // Enable count of allocs if specified in the flags.
   bool enable_stats = false;
 
+  if (runtime->GetJit() != nullptr) {
+    // TODO b/110263880 It would be better if we didn't need to do this.
+    // Since we need to hold the method entrypoint across a suspend to ensure instrumentation
+    // hooks are called correctly we have to disable jit-gc to ensure that the entrypoint doesn't
+    // go away. Furthermore we need to leave this off permanently since one could get the same
+    // effect by causing this to be toggled on and off.
+    runtime->GetJit()->GetCodeCache()->SetGarbageCollectCode(false);
+  }
+
   // Create Trace object.
   {
     // Required since EnableMethodTracing calls ConfigureStubs which visits class linker classes.
diff --git a/runtime/trace.h b/runtime/trace.h
index 582f756..567f6ed 100644
--- a/runtime/trace.h
+++ b/runtime/trace.h
@@ -27,12 +27,12 @@
 #include <vector>
 
 #include "base/atomic.h"
-#include "base/globals.h"
 #include "base/locks.h"
 #include "base/macros.h"
 #include "base/os.h"
 #include "base/safe_map.h"
 #include "instrumentation.h"
+#include "runtime_globals.h"
 
 namespace unix_file {
 class FdFile;
diff --git a/runtime/utils/dex_cache_arrays_layout-inl.h b/runtime/utils/dex_cache_arrays_layout-inl.h
index c0ea6be..3512efe 100644
--- a/runtime/utils/dex_cache_arrays_layout-inl.h
+++ b/runtime/utils/dex_cache_arrays_layout-inl.h
@@ -22,10 +22,10 @@
 #include <android-base/logging.h>
 
 #include "base/bit_utils.h"
-#include "base/globals.h"
 #include "dex/primitive.h"
 #include "gc_root.h"
 #include "mirror/dex_cache.h"
+#include "runtime_globals.h"
 
 namespace art {
 
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 1679821..91eba21 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -2654,6 +2654,7 @@
             // See if instance-of was preceded by a move-object operation, common due to the small
             // register encoding space of instance-of, and propagate type information to the source
             // of the move-object.
+            // Note: this is only valid if the move source was not clobbered.
             uint32_t move_idx = instance_of_idx - 1;
             while (0 != move_idx && !GetInstructionFlags(move_idx).IsOpcode()) {
               move_idx--;
@@ -2663,28 +2664,25 @@
                             work_insn_idx_)) {
               break;
             }
+            auto maybe_update_fn = [&instance_of_inst, update_line, this, &cast_type](
+                uint16_t move_src,
+                uint16_t move_trg)
+                REQUIRES_SHARED(Locks::mutator_lock_) {
+              if (move_trg == instance_of_inst.VRegB_22c() &&
+                  move_src != instance_of_inst.VRegA_22c()) {
+                update_line->SetRegisterType<LockOp::kKeep>(this, move_src, cast_type);
+              }
+            };
             const Instruction& move_inst = code_item_accessor_.InstructionAt(move_idx);
             switch (move_inst.Opcode()) {
               case Instruction::MOVE_OBJECT:
-                if (move_inst.VRegA_12x() == instance_of_inst.VRegB_22c()) {
-                  update_line->SetRegisterType<LockOp::kKeep>(this,
-                                                              move_inst.VRegB_12x(),
-                                                              cast_type);
-                }
+                maybe_update_fn(move_inst.VRegB_12x(), move_inst.VRegA_12x());
                 break;
               case Instruction::MOVE_OBJECT_FROM16:
-                if (move_inst.VRegA_22x() == instance_of_inst.VRegB_22c()) {
-                  update_line->SetRegisterType<LockOp::kKeep>(this,
-                                                              move_inst.VRegB_22x(),
-                                                              cast_type);
-                }
+                maybe_update_fn(move_inst.VRegB_22x(), move_inst.VRegA_22x());
                 break;
               case Instruction::MOVE_OBJECT_16:
-                if (move_inst.VRegA_32x() == instance_of_inst.VRegB_22c()) {
-                  update_line->SetRegisterType<LockOp::kKeep>(this,
-                                                              move_inst.VRegB_32x(),
-                                                              cast_type);
-                }
+                maybe_update_fn(move_inst.VRegB_32x(), move_inst.VRegA_32x());
                 break;
               default:
                 break;
diff --git a/runtime/verify_object.cc b/runtime/verify_object.cc
index 70ca13f..2b8c7da 100644
--- a/runtime/verify_object.cc
+++ b/runtime/verify_object.cc
@@ -17,11 +17,11 @@
 #include "verify_object-inl.h"
 
 #include "base/bit_utils.h"
-#include "base/globals.h"
 #include "gc/heap.h"
 #include "mirror/object-inl.h"
 #include "obj_ptr-inl.h"
 #include "runtime.h"
+#include "runtime_globals.h"
 
 namespace art {
 
diff --git a/test/1001-app-image-regions/app_image_regions.cc b/test/1001-app-image-regions/app_image_regions.cc
new file mode 100644
index 0000000..dc16a84
--- /dev/null
+++ b/test/1001-app-image-regions/app_image_regions.cc
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2019 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 "jni.h"
+
+#include "gc/heap.h"
+#include "gc/space/image_space.h"
+#include "gc/space/space-inl.h"
+#include "gc/space/region_space.h"
+#include "image.h"
+#include "mirror/class.h"
+#include "runtime.h"
+#include "scoped_thread_state_change-inl.h"
+
+namespace art {
+
+namespace {
+
+extern "C" JNIEXPORT jint JNICALL Java_Main_getRegionSize(JNIEnv*, jclass) {
+  return gc::space::RegionSpace::kRegionSize;
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_Main_checkAppImageSectionSize(JNIEnv*, jclass, jclass c) {
+  ScopedObjectAccess soa(Thread::Current());
+  ObjPtr<mirror::Class> klass_ptr = soa.Decode<mirror::Class>(c);
+  for (auto* space : Runtime::Current()->GetHeap()->GetContinuousSpaces()) {
+    if (space->IsImageSpace()) {
+      auto* image_space = space->AsImageSpace();
+      const auto& image_header = image_space->GetImageHeader();
+      if (image_header.IsAppImage() && image_space->HasAddress(klass_ptr.Ptr())) {
+        return image_header.GetObjectsSection().Size();
+      }
+    }
+  }
+  return 0;
+}
+
+}  // namespace
+
+}  // namespace art
diff --git a/test/1001-app-image-regions/build b/test/1001-app-image-regions/build
new file mode 100755
index 0000000..16c3a5b
--- /dev/null
+++ b/test/1001-app-image-regions/build
@@ -0,0 +1,34 @@
+#!/bin/bash
+#
+# Copyright 2019 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.
+
+# make us exit on a failure
+set -e
+
+count=10000
+echo "LMain;" >> profile
+for i in $(seq 1 "$count"); do
+  echo "LOther\$Inner${i};" >> "profile"
+done
+
+# Generate the other class.
+other_file="src/Other.java"
+echo "class Other {" >> "${other_file}"
+for i in $(seq 1 "$count"); do
+  echo "  static class Inner${i} { void test(){} }" >> "${other_file}"
+done
+echo "}" >> "${other_file}"
+
+./default-build "$@"
diff --git a/test/1001-app-image-regions/expected.txt b/test/1001-app-image-regions/expected.txt
new file mode 100644
index 0000000..9fd87ca
--- /dev/null
+++ b/test/1001-app-image-regions/expected.txt
@@ -0,0 +1,4 @@
+JNI_OnLoad called
+App image loaded true
+Region size 262144
+App image section size large enough true
diff --git a/test/1001-app-image-regions/info.txt b/test/1001-app-image-regions/info.txt
new file mode 100644
index 0000000..b13f276
--- /dev/null
+++ b/test/1001-app-image-regions/info.txt
@@ -0,0 +1 @@
+Tests that an app image with many classes is generated and loaded correctly.
diff --git a/test/1001-app-image-regions/run b/test/1001-app-image-regions/run
new file mode 100644
index 0000000..128aa2e
--- /dev/null
+++ b/test/1001-app-image-regions/run
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright (C) 2019 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.
+
+exec ${RUN} $@ --profile -Xcompiler-option --compiler-filter=speed-profile
diff --git a/test/1001-app-image-regions/src/Main.java b/test/1001-app-image-regions/src/Main.java
new file mode 100644
index 0000000..c41a606
--- /dev/null
+++ b/test/1001-app-image-regions/src/Main.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2019 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.
+ */
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+class Main {
+  public static void main(String[] args) {
+    System.loadLibrary(args[0]);
+    System.out.println("App image loaded " + checkAppImageLoaded());
+    int regionSize = getRegionSize();
+    int objectsSectionSize = checkAppImageSectionSize(Main.class);
+    System.out.println("Region size " + regionSize);
+    System.out.println("App image section size large enough " + (objectsSectionSize > regionSize));
+    if (objectsSectionSize <= regionSize) {
+      System.out.println("Section size " + objectsSectionSize);
+    }
+  }
+
+  public static native boolean checkAppImageLoaded();
+  public static native int getRegionSize();
+  public static native int checkAppImageSectionSize(Class c);
+}
diff --git a/test/689-multi-catch/expected.txt b/test/689-multi-catch/expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/689-multi-catch/expected.txt
diff --git a/test/689-multi-catch/info.txt b/test/689-multi-catch/info.txt
new file mode 100644
index 0000000..0778ea8
--- /dev/null
+++ b/test/689-multi-catch/info.txt
@@ -0,0 +1,2 @@
+Regression test for the optimizing compiler which used
+to wrongly type an exception in a multi-catch handler.
diff --git a/test/689-multi-catch/src/Main.java b/test/689-multi-catch/src/Main.java
new file mode 100644
index 0000000..18a17f9
--- /dev/null
+++ b/test/689-multi-catch/src/Main.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+public class Main {
+  public static void main(String[] args) {
+    try {
+      willThrow();
+    } catch (IllegalStateException | NullPointerException e) {
+      if (e instanceof NullPointerException) {
+        return;
+      }
+      throw new Error("Expected NullPointerException");
+    }
+  }
+
+  public static void willThrow() {
+    throw new NullPointerException();
+  }
+}
diff --git a/test/689-zygote-jit-deopt/expected.txt b/test/689-zygote-jit-deopt/expected.txt
new file mode 100644
index 0000000..6a5618e
--- /dev/null
+++ b/test/689-zygote-jit-deopt/expected.txt
@@ -0,0 +1 @@
+JNI_OnLoad called
diff --git a/test/689-zygote-jit-deopt/info.txt b/test/689-zygote-jit-deopt/info.txt
new file mode 100644
index 0000000..100032e
--- /dev/null
+++ b/test/689-zygote-jit-deopt/info.txt
@@ -0,0 +1,2 @@
+Regression test for debuggable apps that need to deoptimize
+methods JIT-compiled by the zygote.
diff --git a/test/689-zygote-jit-deopt/src/Main.java b/test/689-zygote-jit-deopt/src/Main.java
new file mode 100644
index 0000000..330663e
--- /dev/null
+++ b/test/689-zygote-jit-deopt/src/Main.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+public class Main {
+  public static void main(String[] args) {
+    System.loadLibrary(args[0]);
+    if (!hasJit()) {
+      return;
+    }
+    ensureJitCompiled(Object.class, "toString");
+    transitionJitFromZygote();
+    deoptimizeBootImage();
+    if (hasJitCompiledEntrypoint(Object.class, "toString")) {
+      throw new Error("Expected Object.toString to be deoptimized");
+    }
+  }
+
+  private static native boolean hasJit();
+  private static native void ensureJitCompiled(Class<?> cls, String name);
+  private static native boolean hasJitCompiledEntrypoint(Class<?> cls, String name);
+  private static native void deoptimizeBootImage();
+  private static native void transitionJitFromZygote();
+}
diff --git a/test/800-smali/expected.txt b/test/800-smali/expected.txt
index f3c3f03..291de72 100644
--- a/test/800-smali/expected.txt
+++ b/test/800-smali/expected.txt
@@ -73,4 +73,5 @@
 b/30458218
 b/31313170
 ConstClassAliasing
+b/121191566
 Done!
diff --git a/test/800-smali/smali/b_121191566.smali b/test/800-smali/smali/b_121191566.smali
new file mode 100644
index 0000000..bcf9ef5
--- /dev/null
+++ b/test/800-smali/smali/b_121191566.smali
@@ -0,0 +1,26 @@
+.class public LB121191566;
+.super Ljava/lang/Object;
+
+
+.method public constructor <init>()V
+.registers 1
+       invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+       return-void
+.end method
+
+.method public static run(Ljava/lang/Object;)Z
+.registers 5
+       move-object v3, v4
+       instance-of v4, v3, Ljava/lang/String;
+       if-eqz v4, :Branch
+       # The peephole must not overwrite v4 (from the move-object). Use an integral move
+       # to check.
+       move v0, v4
+       goto :End
+:Branch
+       # See above.
+       move v0, v4
+:End
+       # Triple-check: the merge should be consistent.
+       return v0
+.end method
diff --git a/test/800-smali/src/Main.java b/test/800-smali/src/Main.java
index 9b06e9e..d7979e1 100644
--- a/test/800-smali/src/Main.java
+++ b/test/800-smali/src/Main.java
@@ -193,6 +193,8 @@
         testCases.add(new TestCase("b/31313170", "B31313170", "run", null, null, 0));
         testCases.add(new TestCase("ConstClassAliasing", "ConstClassAliasing", "run", null, null,
                 null, true));
+        testCases.add(new TestCase("b/121191566", "B121191566", "run", new Object[] { "a" }, null,
+                true, false));
     }
 
     public void runTests() {
diff --git a/test/Android.bp b/test/Android.bp
index 57fcd86..467a717 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -495,6 +495,7 @@
         "708-jit-cache-churn/jit.cc",
         "800-smali/jni.cc",
         "909-attach-agent/disallow_debugging.cc",
+        "1001-app-image-regions/app_image_regions.cc",
         "1947-breakpoint-redefine-deopt/check_deopt.cc",
         "common/runtime_state.cc",
         "common/stack_inspect.cc",
diff --git a/test/common/runtime_state.cc b/test/common/runtime_state.cc
index 55631a9..bbc3039 100644
--- a/test/common/runtime_state.cc
+++ b/test/common/runtime_state.cc
@@ -161,6 +161,19 @@
   return !interpreter;
 }
 
+static ArtMethod* GetMethod(ScopedObjectAccess& soa, jclass cls, const ScopedUtfChars& chars)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  CHECK(chars.c_str() != nullptr);
+  ArtMethod* method = soa.Decode<mirror::Class>(cls)->FindDeclaredDirectMethodByName(
+        chars.c_str(), kRuntimePointerSize);
+  if (method == nullptr) {
+    method = soa.Decode<mirror::Class>(cls)->FindDeclaredVirtualMethodByName(
+        chars.c_str(), kRuntimePointerSize);
+  }
+  DCHECK(method != nullptr) << "Unable to find method called " << chars.c_str();
+  return method;
+}
+
 extern "C" JNIEXPORT jboolean JNICALL Java_Main_hasJitCompiledEntrypoint(JNIEnv* env,
                                                                          jclass,
                                                                          jclass cls,
@@ -172,9 +185,7 @@
   Thread* self = Thread::Current();
   ScopedObjectAccess soa(self);
   ScopedUtfChars chars(env, method_name);
-  CHECK(chars.c_str() != nullptr);
-  ArtMethod* method = soa.Decode<mirror::Class>(cls)->FindDeclaredDirectMethodByName(
-        chars.c_str(), kRuntimePointerSize);
+  ArtMethod* method = GetMethod(soa, cls, chars);
   ScopedAssertNoThreadSuspension sants(__FUNCTION__);
   return jit->GetCodeCache()->ContainsPc(
       Runtime::Current()->GetInstrumentation()->GetCodeForInvoke(method));
@@ -191,9 +202,7 @@
   Thread* self = Thread::Current();
   ScopedObjectAccess soa(self);
   ScopedUtfChars chars(env, method_name);
-  CHECK(chars.c_str() != nullptr);
-  ArtMethod* method = soa.Decode<mirror::Class>(cls)->FindDeclaredDirectMethodByName(
-        chars.c_str(), kRuntimePointerSize);
+  ArtMethod* method = GetMethod(soa, cls, chars);
   return jit->GetCodeCache()->ContainsMethod(method);
 }
 
@@ -262,14 +271,7 @@
     ScopedObjectAccess soa(self);
 
     ScopedUtfChars chars(env, method_name);
-    CHECK(chars.c_str() != nullptr);
-    method = soa.Decode<mirror::Class>(cls)->FindDeclaredDirectMethodByName(
-        chars.c_str(), kRuntimePointerSize);
-    if (method == nullptr) {
-      method = soa.Decode<mirror::Class>(cls)->FindDeclaredVirtualMethodByName(
-          chars.c_str(), kRuntimePointerSize);
-    }
-    DCHECK(method != nullptr) << "Unable to find method called " << chars.c_str();
+    method = GetMethod(soa, cls, chars);
   }
   ForceJitCompiled(self, method);
 }
@@ -353,4 +355,20 @@
   return (jit != nullptr) ? jit->HotMethodThreshold() : 0;
 }
 
+extern "C" JNIEXPORT void JNICALL Java_Main_transitionJitFromZygote(JNIEnv*, jclass) {
+  jit::Jit* jit = Runtime::Current()->GetJit();
+  if (jit == nullptr) {
+    return;
+  }
+  // Mimic the transition behavior a zygote fork would have.
+  jit->PreZygoteFork();
+  jit->GetCodeCache()->PostForkChildAction(/*is_system_server=*/ false, /*is_zygote=*/ false);
+  jit->PostForkChildAction(/*is_zygote=*/ false);
+}
+
+extern "C" JNIEXPORT void JNICALL Java_Main_deoptimizeBootImage(JNIEnv*, jclass) {
+  ScopedSuspendAll ssa(__FUNCTION__);
+  Runtime::Current()->DeoptimizeBootImage();
+}
+
 }  // namespace art
diff --git a/test/common/stack_inspect.cc b/test/common/stack_inspect.cc
index 393e773..cb011a8 100644
--- a/test/common/stack_inspect.cc
+++ b/test/common/stack_inspect.cc
@@ -18,6 +18,7 @@
 
 #include <android-base/logging.h>
 
+#include "arch/context.h"
 #include "base/mutex.h"
 #include "dex/dex_file-inl.h"
 #include "jni/jni_internal.h"
diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar
index 25b8b4b..3074763 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -319,6 +319,10 @@
         shift
         ANDROID_ROOT="$1"
         shift
+    elif [ "x$1" = "x--android-runtime-root" ]; then
+        shift
+        ANDROID_RUNTIME_ROOT="$1"
+        shift
     elif [ "x$1" = "x--instruction-set-features" ]; then
         shift
         INSTRUCTION_SET_FEATURES="$1"
diff --git a/test/knownfailures.json b/test/knownfailures.json
index 983c16a..9c01ba9 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -81,11 +81,13 @@
         "variant": "no-prebuild"
     },
     {
-        "tests": ["118-noimage-dex2oat"],
+        "tests": ["118-noimage-dex2oat",
+                  "1001-app-image-regions"],
         "variant": "no-relocate",
         "description": ["118-noimage-dex2oat is not broken per-se it just ",
                         "doesn't work (and isn't meant to) without --prebuild ",
-                        "--relocate"]
+                        "--relocate. 1001-app-image-regions is disabled since it",
+                        "doesn't have the app image loaded for no-relocate"]
     },
     {
         "tests" : "629-vdex-speed",
@@ -1085,6 +1087,7 @@
                   "688-shared-library",
                   "999-redefine-hiddenapi",
                   "1000-non-moving-space-stress",
+                  "1001-app-image-regions",
                   "1951-monitor-enter-no-suspend",
                   "1957-error-ext"],
         "variant": "jvm",
diff --git a/test/run-test b/test/run-test
index 83c726e..67bcce7 100755
--- a/test/run-test
+++ b/test/run-test
@@ -386,6 +386,15 @@
         android_root="$1"
         run_args="${run_args} --android-root $1"
         shift
+    elif [ "x$1" = "x--android-runtime-root" ]; then
+        shift
+        if [ "x$1" = "x" ]; then
+            echo "$0 missing argument to --android-runtime-root" 1>&2
+            usage="yes"
+            break
+        fi
+        run_args="${run_args} --android-runtime-root $1"
+        shift
     elif [ "x$1" = "x--update" ]; then
         update_mode="yes"
         shift
@@ -758,6 +767,9 @@
         echo "    --never-clean         Keep the test files even if the test succeeds."
         echo "    --chroot [newroot]    Run with root directory set to newroot."
         echo "    --android-root [path] The path on target for the android root. (/system by default)."
+        echo "    --android-runtime-root [path]"
+        echo "                          The path on target for the Android Runtime root."
+        echo "                          (/apex/com.android.runtime by default)."
         echo "    --dex2oat-swap        Use a dex2oat swap file."
         echo "    --instruction-set-features [string]"
         echo "                          Set instruction-set-features for compilation."
diff --git a/test/testrunner/env.py b/test/testrunner/env.py
index 1f4b829..c2d5e7d 100644
--- a/test/testrunner/env.py
+++ b/test/testrunner/env.py
@@ -89,8 +89,8 @@
   HOST_2ND_ARCH_PREFIX + 'DEX2OAT_HOST_INSTRUCTION_SET_FEATURES')
 
 ART_TEST_CHROOT = _env.get('ART_TEST_CHROOT')
-
 ART_TEST_ANDROID_ROOT = _env.get('ART_TEST_ANDROID_ROOT')
+ART_TEST_ANDROID_RUNTIME_ROOT = _env.get('ART_TEST_ANDROID_RUNTIME_ROOT')
 
 ART_TEST_WITH_STRACE = _getEnvBoolean('ART_TEST_DEBUG_GC', False)
 
diff --git a/test/testrunner/testrunner.py b/test/testrunner/testrunner.py
index 4e873c1..0456fdb 100755
--- a/test/testrunner/testrunner.py
+++ b/test/testrunner/testrunner.py
@@ -400,12 +400,15 @@
       elif target == 'jvm':
         options_test += ' --jvm'
 
-      # Honor ART_TEST_CHROOT and ART_TEST_ANDROID_ROOT, but only for target tests.
+      # Honor ART_TEST_CHROOT, ART_TEST_ANDROID_ROOT and ART_TEST_ANDROID_RUNTIME_ROOT,
+      # but only for target tests.
       if target == 'target':
         if env.ART_TEST_CHROOT:
           options_test += ' --chroot ' + env.ART_TEST_CHROOT
         if env.ART_TEST_ANDROID_ROOT:
           options_test += ' --android-root ' + env.ART_TEST_ANDROID_ROOT
+        if env.ART_TEST_ANDROID_RUNTIME_ROOT:
+          options_test += ' --android-runtime-root ' + env.ART_TEST_ANDROID_RUNTIME_ROOT
 
       if run == 'ndebug':
         options_test += ' -O'
diff --git a/tools/art b/tools/art
index eeb7c68..2c28807 100644
--- a/tools/art
+++ b/tools/art
@@ -199,6 +199,7 @@
     # (see run_art function)
     verbose_run ANDROID_DATA=$ANDROID_DATA                    \
           ANDROID_ROOT=$ANDROID_ROOT                          \
+          ANDROID_RUNTIME_ROOT=$ANDROID_RUNTIME_ROOT          \
           LD_LIBRARY_PATH=$LD_LIBRARY_PATH                    \
           PATH=$ANDROID_ROOT/bin:$PATH                        \
           LD_USE_LOAD_BIAS=1                                  \
@@ -222,6 +223,8 @@
 # -Xcompiler-options arguments are stored in DEX2OAT_FLAGS array
 # -cp argument is split by ':' and stored in DEX2OAT_CLASSPATH
 # -Ximage argument is stored in DEX2OAT_BOOT_IMAGE
+# -Xbootclasspath argument is stored in DEX2OAT_BCP
+# -Xbootclasspath-locations argument is stored in DEX2OAT_BCP_LOCS
 function extract_dex2oat_flags() {
   while [ $# -gt 0 ]; do
     case $1 in
@@ -234,6 +237,16 @@
         # Remove '-Ximage:' from the argument.
         DEX2OAT_BOOT_IMAGE=${DEX2OAT_BOOT_IMAGE##-Ximage:}
         ;;
+      -Xbootclasspath:*)
+        DEX2OAT_BCP=$1
+        # Remove '-Xbootclasspath:' from the argument.
+        DEX2OAT_BCP=${DEX2OAT_BCP##-Xbootclasspath:}
+        ;;
+      -Xbootclasspath-locations:*)
+        DEX2OAT_BCP_LOCS=$1
+        # Remove '-Xbootclasspath-locations:' from the argument.
+        DEX2OAT_BCP_LOCS=${DEX2OAT_BCP_LOCS##-Xbootclasspath-locations:}
+        ;;
       -cp)
         # Reset any previously parsed classpath, just like dalvikvm
         # only supports one -cp argument.
@@ -386,8 +399,42 @@
 done
 
 PROG_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
-ANDROID_ROOT=$PROG_DIR/..
-ANDROID_RUNTIME_ROOT=$ANDROID_ROOT/com.android.runtime
+ANDROID_ROOT="$(cd $PROG_DIR/..; pwd -P)"
+
+# If ANDROID_RUNTIME_ROOT is not set, try to detect whether we are running on
+# target or host and set that environment variable to the usual default value.
+if [ -z "$ANDROID_RUNTIME_ROOT" ]; then
+  # This script is used on host and target (device). However, the (expected)
+  # default value `ANDROID_RUNTIME_ROOT` is not the same on host and target:
+  # - on host, `ANDROID_RUNTIME_ROOT` is expected to be "$ANDROID_ROOT/com.android.apex";
+  # - on target, `ANDROID_RUNTIME_ROOT` is expected to be "$ANDROID_ROOT/../apex/com.android.apex".
+  #
+  # We use the presence/absence of the `$ANDROID_ROOT/../apex` directory to
+  # determine whether we are on target or host (this is brittle, but simple).
+  if [ -d "$ANDROID_ROOT/../apex" ]; then
+    # Target case.
+    #
+    # We should be setting `ANDROID_RUNTIME_ROOT` to
+    # "$ANDROID_ROOT/../apex/com.android.runtime" here. However, the Runtime APEX
+    # is not (yet) supported by the ART Buildbot setup (see b/121117762); and yet
+    # ICU code depends on `ANDROID_RUNTIME_ROOT` to find ICU .dat files.
+    #
+    # As a temporary workaround, we:
+    # - make the ART Buildbot build script (art/tools/buildbot-build.sh) also
+    #   generate the ICU .dat files in `/system/etc/icu` on device (these files
+    #   are normally only put in the Runtime APEX on device);
+    # - set `ANDROID_RUNTIME_ROOT` to `$ANDROID_ROOT` (i.e. "/system") here.
+    #
+    # TODO(b/121117762): Set `ANDROID_RUNTIME_ROOT` to
+    # "$ANDROID_ROOT/../apex/com.android.runtime" when the Runtime APEX is fully
+    # supported on the ART Buildbot and Golem.
+    ANDROID_RUNTIME_ROOT=$ANDROID_ROOT
+  else
+    # Host case.
+    ANDROID_RUNTIME_ROOT="$ANDROID_ROOT/com.android.runtime"
+  fi
+fi
+
 ART_BINARY_PATH=$ANDROID_ROOT/bin/$ART_BINARY
 
 if [ ! -x "$ART_BINARY_PATH" ]; then
@@ -422,7 +469,7 @@
 # Extract the dex2oat flags from the list of arguments.
 # -Xcompiler-options arguments are stored in DEX2OAT_FLAGS array
 # -cp argument is split by ':' and stored in DEX2OAT_CLASSPATH
-# -Ximage argument is stored in DEX2OAT_BOOTIMAGE
+# -Ximage argument is stored in DEX2OAT_BOOT_IMAGE
 extract_dex2oat_flags "$@"
 
 # If ANDROID_DATA is the system ANDROID_DATA or is not set, use our own,
@@ -439,6 +486,55 @@
   DELETE_ANDROID_DATA="yes"
 fi
 
+if [[ "$DEX2OAT_BCP" = "" && "$DEX2OAT_BCP_LOCS" != "" ]]; then
+  echo "Cannot use -Xbootclasspath-locations without -Xbootclasspath"
+  exit 1
+fi
+
+if [[ "$DEX2OAT_BOOT_IMAGE" = *core*.art && "$DEX2OAT_BCP" = "" ]]; then
+  # Note: This must start with the CORE_IMG_JARS in Android.common_path.mk
+  # because that's what we use for compiling the core.art image.
+  # It may contain additional modules from TEST_CORE_JARS.
+  core_jars_list="core-oj core-libart core-simple okhttp bouncycastle apache-xml conscrypt"
+  core_jars_suffix=
+  if [[ -e $ANDROID_ROOT/framework/core-oj-hostdex.jar ]]; then
+    core_jars_suffix=-hostdex
+    core_locations_dir=$ANDROID_ROOT/framework
+    prefix=$PWD/
+    if [[ ${core_locations_dir:0:${#prefix}} = $prefix ]]; then
+      core_locations_dir="${core_locations_dir##$prefix}"
+    fi
+  elif [[ -e $ANDROID_ROOT/framework/core-oj-testdex.jar ]]; then
+    core_jars_suffix=-testdex
+    core_locations_dir=/system/framework
+  fi
+  if [[ $core_jars_suffix != "" ]]; then
+    boot_separator=""
+    for boot_module in ${core_jars_list}; do
+      DEX_FILENAME="$boot_module$core_jars_suffix.jar"
+      DEX2OAT_BCP+="$boot_separator$ANDROID_ROOT/framework/${DEX_FILENAME}"
+      DEX2OAT_BCP_LOCS+="$boot_separator$core_locations_dir/${DEX_FILENAME}"
+      boot_separator=":"
+    done
+    if [ "$VERBOSE" = "yes" ]; then
+      echo "Using predefined -Xbootclasspath for image $DEX2OAT_BOOT_IMAGE:"
+      echo DEX2OAT_BOOT_IMAGE=$DEX2OAT_BOOT_IMAGE
+      echo DEX2OAT_BCP=$DEX2OAT_BCP
+      echo DEX2OAT_BCP_LOCS=$DEX2OAT_BCP_LOCS
+    fi
+  fi
+fi
+
+if [ "$DEX2OAT_BCP" != "" ]; then
+  EXTRA_OPTIONS+=("-Xbootclasspath:$DEX2OAT_BCP")
+  DEX2OAT_FLAGS+=("--runtime-arg" "-Xbootclasspath:$DEX2OAT_BCP")
+  if [ "$DEX2OAT_BCP_LOCS" != "" ]; then
+    EXTRA_OPTIONS+=("-Xbootclasspath-locations:$DEX2OAT_BCP_LOCS")
+    DEX2OAT_FLAGS+=("--runtime-arg" \
+                    "-Xbootclasspath-locations:$DEX2OAT_BCP_LOCS")
+  fi
+fi
+
 if [ "$PERF" != "" ]; then
   LAUNCH_WRAPPER="perf record -g --call-graph dwarf -F 10000 -o $ANDROID_DATA/perf.data -e cycles:u $LAUNCH_WRAPPER"
   DEX2OAT_FLAGS+=(--generate-debug-info)
diff --git a/tools/buildbot-build.sh b/tools/buildbot-build.sh
index da463d5..755104b 100755
--- a/tools/buildbot-build.sh
+++ b/tools/buildbot-build.sh
@@ -73,7 +73,7 @@
     exit 1
   fi
   make_command="make $j_arg $extra_args $showcommands build-art-target-tests $common_targets"
-  make_command+=" libjavacrypto-target libnetd_client-target linker toybox toolbox sh"
+  make_command+=" libjavacrypto-target libnetd_client-target linker toybox toolbox sh unzip"
   make_command+=" debuggerd su"
   make_command+=" libstdc++ "
   make_command+=" ${ANDROID_PRODUCT_OUT#"${ANDROID_BUILD_TOP}/"}/system/etc/public.libraries.txt"
@@ -81,8 +81,25 @@
     # These targets are needed for the chroot environment.
     make_command+=" crash_dump event-log-tags"
   fi
-  # Build the Runtime APEX.
-  make_command+=" com.android.runtime"
+  # Build the Debug Runtime APEX (which is a superset of the Release Runtime APEX).
+  make_command+=" com.android.runtime.debug"
+  # Build the bootstrap Bionic libraries (libc, libdl, libm). These are required
+  # as the "main" libc, libdl, and libm have moved to the Runtime APEX. This is
+  # a temporary change needed until both the ART Buildbot and Golem fully
+  # support the Runtime APEX.
+  #
+  # TODO(b/121117762): Remove this when the ART Buildbot and Golem have full
+  # support for the Runtime APEX.
+  make_command+=" libc.bootstrap libdl.bootstrap libm.bootstrap"
+  # Create a copy of the ICU .dat prebuilt files in /system/etc/icu on target,
+  # so that it can found even if the Runtime APEX is not available, by setting
+  # the environment variable `ART_TEST_ANDROID_RUNTIME_ROOT` to "/system" on
+  # device. This is a temporary change needed until both the ART Buildbot and
+  # Golem fully support the Runtime APEX.
+  #
+  # TODO(b/121117762): Remove this when the ART Buildbot and Golem have full
+  # support for the Runtime APEX.
+  make_command+=" icu-data-art-test"
   mode_suffix="-target"
 fi
 
diff --git a/tools/cpp-define-generator/globals.def b/tools/cpp-define-generator/globals.def
index 6443a0c..1054262 100644
--- a/tools/cpp-define-generator/globals.def
+++ b/tools/cpp-define-generator/globals.def
@@ -26,6 +26,7 @@
 #include "jit/jit.h"
 #include "mirror/object.h"
 #include "mirror/object_reference.h"
+#include "runtime_globals.h"
 #include "stack.h"
 #endif
 
diff --git a/tools/hiddenapi/hiddenapi.cc b/tools/hiddenapi/hiddenapi.cc
index 6af822d..86e5f54 100644
--- a/tools/hiddenapi/hiddenapi.cc
+++ b/tools/hiddenapi/hiddenapi.cc
@@ -34,6 +34,8 @@
 
 namespace art {
 
+const char kErrorHelp[] = "\nSee go/hiddenapi-error for help.";
+
 static int original_argc;
 static char** original_argv;
 
@@ -983,16 +985,27 @@
 
     std::map<std::string, hiddenapi::ApiList> api_flag_map;
 
-    for (std::string line; std::getline(api_file, line);) {
+    int line_number = 1;
+    for (std::string line; std::getline(api_file, line); line_number++) {
       std::vector<std::string> values = android::base::Split(line, ",");
-      CHECK_EQ(values.size(), 2u) << "Currently only signature and one flag are supported";
-
+      CHECK_GT(values.size(), 1u) << path << ":" << line_number << ": No flags found"
+          << kErrorHelp;
       const std::string& signature = values[0];
-      CHECK(api_flag_map.find(signature) == api_flag_map.end()) << "Duplicate entry: " << signature;
+
+      CHECK(api_flag_map.find(signature) == api_flag_map.end()) << "Duplicate entry in " << path
+          << ": " << signature << kErrorHelp;
+
+      int numFlags = values.size() - 1;
+
+      CHECK_EQ(numFlags, 1) << "\n" << path << ":" << line_number << "\n"
+          << signature << ": Expected one flag, found " << numFlags << ":\n"
+          << ::android::base::Join(std::vector<std::string>(values.begin() + 1, values.end()), ",")
+          << kErrorHelp;
 
       const std::string& flag_str = values[1];
       hiddenapi::ApiList membership = hiddenapi::ApiList::FromName(flag_str);
-      CHECK(membership.IsValid()) << "Unknown ApiList name: " << flag_str;
+      CHECK(membership.IsValid()) << path << ":" << line_number << ": Unknown ApiList name: "
+          << flag_str << kErrorHelp;
 
       api_flag_map.emplace(signature, membership);
     }
diff --git a/tools/libcore_failures.txt b/tools/libcore_failures.txt
index 3c65b01..7ef20bd 100644
--- a/tools/libcore_failures.txt
+++ b/tools/libcore_failures.txt
@@ -17,13 +17,13 @@
 {
   description: "Differences between vogar and cts in user directory",
   result: EXEC_FAILED,
-  modes: [device],
+  modes: [device_testdex],
   name: "libcore.java.lang.SystemTest#testSystemProperties_mutable"
 },
 {
   description: "Differences between vogar and cts. Passes with --mode activity",
   result: EXEC_FAILED,
-  modes: [device],
+  modes: [device_testdex],
   names: ["libcore.java.lang.OldSystemTest#test_getProperties"]
 },
 {
@@ -32,7 +32,7 @@
                 (--invoke-with \"su root\"). Does not pass after setting chmod
                 777 all directories on path to socket (on device without su).",
   result: EXEC_FAILED,
-  modes: [device],
+  modes: [device_testdex],
   names: ["libcore.libcore.io.OsTest#testUnixDomainSockets_in_file_system"]
 },
 {
@@ -47,7 +47,7 @@
 {
   description: "Issue with incorrect device time (1970)",
   result: EXEC_FAILED,
-  modes: [device],
+  modes: [device_testdex],
   names: ["libcore.java.util.TimeZoneTest#testDisplayNames",
           "libcore.java.util.TimeZoneTest#test_useDaylightTime_Taiwan",
           "org.apache.harmony.tests.java.util.TimeZoneTest#test_hasSameRules_Ljava_util_TimeZone"],
@@ -57,13 +57,13 @@
   description: "Issue with incorrect device time (1970). Test assumes that DateTime.now()
                 is greater then a date in 1998.",
   result: EXEC_FAILED,
-  modes: [device],
+  modes: [device_testdex],
   names: ["org.apache.harmony.tests.java.util.DateTest#test_Constructor"]
 },
 {
   description: "Failing due to a locale problem on hammerhead.",
   result: EXEC_FAILED,
-  modes: [device],
+  modes: [device_testdex],
   names: ["libcore.icu.DateIntervalFormatTest#test10089890",
           "libcore.icu.DateIntervalFormatTest#test10209343_when_not_this_year",
           "libcore.icu.DateIntervalFormatTest#test10560853_for_single_day_events",
@@ -80,7 +80,7 @@
 {
   description: "Failing due to missing localhost on hammerhead and volantis.",
   result: EXEC_FAILED,
-  modes: [device],
+  modes: [device_testdex],
   names: ["libcore.javax.crypto.CipherTest#testCipherInitWithCertificate",
           "libcore.net.NetworkSecurityPolicyTest#testCleartextTrafficPolicyWithFtpURLConnection",
           "libcore.net.NetworkSecurityPolicyTest#testCleartextTrafficPolicyWithJarFtpURLConnection",
@@ -95,13 +95,13 @@
 {
   description: "Test timeouts",
   result: EXEC_TIMEOUT,
-  modes: [device],
+  modes: [device_testdex],
   names: ["org.apache.harmony.tests.java.util.ScannerTest#testPerformance"]
 },
 {
   description: "Needs the newest cat version on the device",
   result: EXEC_FAILED,
-  modes: [device],
+  modes: [device_testdex],
   names: ["org.apache.harmony.tests.java.lang.ProcessTest#test_getErrorStream"]
 },
 {
@@ -117,7 +117,7 @@
 },
 {
   description: "Linker issues in chrooted environment",
-  modes: [device],
+  modes: [device_testdex],
   result: EXEC_FAILED,
   names: ["org.apache.harmony.tests.java.lang.ProcessManagerTest#testEnvironment"]
 },
@@ -130,14 +130,14 @@
 {
   description: "test_xattr fails on arm64 on the buildbots only: needs investigation",
   result: EXEC_FAILED,
-  modes: [device],
+  modes: [device_testdex],
   names: ["libcore.libcore.io.OsTest#test_xattr"],
   bug: 22258911
 },
 {
   description: "fails on L builds: needs investigation",
   result: EXEC_FAILED,
-  modes: [device],
+  modes: [device_testdex],
   names: ["org.apache.harmony.tests.java.lang.ClassTest#test_forNameLjava_lang_String"]
 },
 {
@@ -163,7 +163,7 @@
   description: "Flaky test",
   result: EXEC_FAILED,
   bug: 30107038,
-  modes: [device],
+  modes: [device_testdex],
   names: ["org.apache.harmony.tests.java.lang.ProcessTest#test_destroyForcibly"]
 },
 {
@@ -171,7 +171,7 @@
                 Unclear if this relates to the tests running sh as a child process.",
   result: EXEC_FAILED,
   bug: 30657148,
-  modes: [device],
+  modes: [device_testdex],
   names: ["libcore.java.lang.ProcessBuilderTest#testRedirectInherit",
           "libcore.java.lang.ProcessBuilderTest#testRedirect_nullStreams"]
 },
@@ -195,7 +195,7 @@
 {
   description: "Timeout on heap-poisoning target builds",
   result: EXEC_FAILED,
-  modes: [device],
+  modes: [device_testdex],
   bug: 116446372,
   names: ["libcore.libcore.io.FdsanTest#testSocket"]
 },
@@ -223,5 +223,17 @@
     "libcore.libcore.net.InetAddressUtilsTest#test_parseNonNumericAddress[8]",
     "libcore.libcore.net.InetAddressUtilsTest#test_parseNonNumericAddress[9]"
   ]
+},
+{
+  description: "Apex related",
+  result: EXEC_FAILED,
+  modes: [device_testdex],
+  bug: 122642227,
+  names: [
+    "libcore.java.lang.SystemTest#testSystemProperties_mutable",
+    "libcore.libcore.icu.TimeZoneIntegrationTest#testTimeZoneDataVersion",
+    "libcore.libcore.icu.TimeZoneIntegrationTest#testTimeZoneDebugInfo",
+    "libcore.libcore.icu.TimeZoneIntegrationTest#testTzDataSetVersions"
+  ]
 }
 ]
diff --git a/tools/libcore_gcstress_debug_failures.txt b/tools/libcore_gcstress_debug_failures.txt
index 23533af..25a4c82 100644
--- a/tools/libcore_gcstress_debug_failures.txt
+++ b/tools/libcore_gcstress_debug_failures.txt
@@ -7,7 +7,7 @@
 {
   description: "Timeouts on target with gcstress and debug.",
   result: EXEC_FAILED,
-  modes: [device],
+  modes: [device_testdex],
   names: ["jsr166.CompletableFutureTest#testCompleteOnTimeout_completed",
           "jsr166.CompletableFutureTest#testDelayedExecutor",
           "jsr166.ExecutorsTest#testTimedCallable",
diff --git a/tools/libcore_gcstress_failures.txt b/tools/libcore_gcstress_failures.txt
index eec45fa..34ede69 100644
--- a/tools/libcore_gcstress_failures.txt
+++ b/tools/libcore_gcstress_failures.txt
@@ -7,7 +7,7 @@
 {
   description: "Timeouts on target with gcstress.",
   result: EXEC_FAILED,
-  modes: [device],
+  modes: [device_testdex],
   names: ["libcore.javax.crypto.CipherBasicsTest#testGcmEncryption"]
 },
 {
@@ -26,7 +26,7 @@
 {
   description: "Timeouts.",
   result: EXEC_FAILED,
-  modes: [device],
+  modes: [device_testdex],
   names: ["jsr166.TimeUnitTest#testConvert",
           "libcore.java.lang.StringTest#testFastPathString_wellFormedUtf8Sequence",
           "libcore.java.text.DecimalFormatTest#testCurrencySymbolSpacing",
diff --git a/tools/mount-buildbot-apexes.sh b/tools/mount-buildbot-apexes.sh
new file mode 100755
index 0000000..778d634
--- /dev/null
+++ b/tools/mount-buildbot-apexes.sh
@@ -0,0 +1,79 @@
+#!/bin/bash
+#
+# Copyright (C) 2019 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.
+
+# Mount Android Runtime and Core Libraries APEX packages required in the chroot directory.
+# This script emulates some the actions performed by `apexd`.
+
+green='\033[0;32m'
+nc='\033[0m'
+
+# Setup as root, as some actions performed here require it.
+adb root
+adb wait-for-device
+
+# Exit early if there is no chroot.
+[[ -n "$ART_TEST_CHROOT" ]] || exit
+
+# Check that ART_TEST_CHROOT is correctly defined.
+[[ "$ART_TEST_CHROOT" = /* ]] || { echo "$ART_TEST_CHROOT is not an absolute path"; exit 1; }
+
+# Check that the "$ART_TEST_CHROOT/apex" directory exists.
+adb shell test -d "$ART_TEST_CHROOT/apex" \
+  || { echo "$ART_TEST_CHROOT/apex does not exist or is not a directory"; exit 1; }
+
+# Create a directory where we extract APEX packages' payloads (ext4 images)
+# under the chroot directory.
+apex_image_dir="/tmp/apex"
+adb shell mkdir -p "$ART_TEST_CHROOT$apex_image_dir"
+
+# activate_system_package APEX_PACKAGE APEX_NAME
+# ----------------------------------------------
+# Extract payload (ext4 image) from system APEX_PACKAGE and mount it as
+# APEX_NAME in `/apex` under the chroot directory.
+activate_system_package() {
+  local apex_package=$1
+  local apex_name=$2
+  local apex_package_path="/system/apex/$apex_package"
+  local abs_mount_point="$ART_TEST_CHROOT/apex/$apex_name"
+  local abs_image_filename="$ART_TEST_CHROOT$apex_image_dir/$apex_name.img"
+
+  # Make sure that the (absolute) path to the mounted ext4 image is less than
+  # 64 characters, which is a hard limit set in the kernel for loop device
+  # filenames (otherwise, we would get an error message from `losetup`, used
+  # by `mount` to manage the loop device).
+  [[ "${#abs_image_filename}" -ge 64 ]] \
+    && { echo "Filename $abs_image_filename is too long to be used with a loop device"; exit 1; }
+
+  echo -e "${green}Activating package $apex_package as $apex_name${nc}"
+
+  # Extract payload (ext4 image). As standard Android builds do not contain
+  # `unzip`, we use the one we built and sync'd to the chroot directory instead.
+  local payload_filename="apex_payload.img"
+  adb shell chroot "$ART_TEST_CHROOT" \
+    /system/bin/unzip -q "$apex_package_path" "$payload_filename" -d "$apex_image_dir"
+  # Rename the extracted payload to have its name match the APEX's name.
+  adb shell mv "$ART_TEST_CHROOT$apex_image_dir/$payload_filename" "$abs_image_filename"
+  # Check that the mount point is available.
+  adb shell mount | grep -q " on $abs_mount_point" && \
+    { echo "$abs_mount_point is already used as mount point"; exit 1; }
+  # Mount the ext4 image.
+  adb shell mkdir -p "$abs_mount_point"
+  adb shell mount -o loop,ro "$abs_image_filename" "$abs_mount_point"
+}
+
+# Activate the Android Runtime APEX.
+# Note: We use the Debug Runtime APEX (which is a superset of the Release Runtime APEX).
+activate_system_package com.android.runtime.debug.apex com.android.runtime
diff --git a/tools/run-jdwp-tests.sh b/tools/run-jdwp-tests.sh
index c7503bb..ac9f09a 100755
--- a/tools/run-jdwp-tests.sh
+++ b/tools/run-jdwp-tests.sh
@@ -125,6 +125,11 @@
     # Vogar knows which VM to use on host.
     vm_command=""
     shift
+  elif [[ "$1" == "--mode=device" ]]; then
+    # Remove the --mode=device from the arguments and replace it with --mode=device_testdex
+    args=${args/$1}
+    args="$args --mode=device_testdex"
+    shift
   elif [[ "$1" == "--mode=jvm" ]]; then
     mode="ri"
     make_target_name="apache-harmony-jdwp-tests-host"
diff --git a/tools/run-libcore-tests.sh b/tools/run-libcore-tests.sh
index 68c4fd8..ea7464f 100755
--- a/tools/run-libcore-tests.sh
+++ b/tools/run-libcore-tests.sh
@@ -125,6 +125,9 @@
 while true; do
   if [[ "$1" == "--mode=device" ]]; then
     device_mode=true
+    # Remove the --mode=device from the arguments and replace it with --mode=device_testdex
+    vogar_args=${vogar_args/$1}
+    vogar_args="$vogar_args --mode=device_testdex"
     vogar_args="$vogar_args --vm-arg -Ximage:/data/art-test/core.art"
     vogar_args="$vogar_args $(boot_classpath_arg /system/framework -testdex $BOOT_CLASSPATH_JARS)"
     shift
diff --git a/tools/setup-buildbot-device.sh b/tools/setup-buildbot-device.sh
index ef958d6..92b3672 100755
--- a/tools/setup-buildbot-device.sh
+++ b/tools/setup-buildbot-device.sh
@@ -165,4 +165,9 @@
   adb shell mkdir -p "$ART_TEST_CHROOT/dev"
   adb shell mount | grep -q "^tmpfs on $ART_TEST_CHROOT/dev type tmpfs " \
     || adb shell mount -o bind /dev "$ART_TEST_CHROOT/dev"
+
+  # Create /apex tmpfs in chroot.
+  adb shell mkdir -p "$ART_TEST_CHROOT/apex"
+  adb shell mount | grep -q "^tmpfs on $ART_TEST_CHROOT/apex type tmpfs " \
+    || adb shell mount -t tmpfs -o nodev,noexec,nosuid tmpfs "$ART_TEST_CHROOT/apex"
 fi
diff --git a/tools/teardown-buildbot-device.sh b/tools/teardown-buildbot-device.sh
index 6634fb4..7eb5cc3 100755
--- a/tools/teardown-buildbot-device.sh
+++ b/tools/teardown-buildbot-device.sh
@@ -89,6 +89,9 @@
            fi
     }
 
+    # Remove /apex from chroot.
+    remove_filesystem_from_chroot apex tmpfs true
+
     # Remove /dev from chroot.
     remove_filesystem_from_chroot dev tmpfs true
 
diff --git a/tools/unmount-buildbot-apexes.sh b/tools/unmount-buildbot-apexes.sh
new file mode 100755
index 0000000..8f0ad5f
--- /dev/null
+++ b/tools/unmount-buildbot-apexes.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+#
+# Copyright (C) 2019 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.
+
+# Unmount Android Runtime and Core Libraries APEX packages required in the chroot directory.
+# This script emulates some the actions performed by `apexd`.
+
+# This script undoes the work done by tools/mount-buildbot-apexes.sh.
+# Make sure to keep these files in sync.
+
+green='\033[0;32m'
+nc='\033[0m'
+
+# Setup as root, as some actions performed here require it.
+adb root
+adb wait-for-device
+
+# Exit early if there is no chroot.
+[[ -n "$ART_TEST_CHROOT" ]] || exit
+
+# Check that ART_TEST_CHROOT is correctly defined.
+[[ "$ART_TEST_CHROOT" = /* ]] || { echo "$ART_TEST_CHROOT is not an absolute path"; exit 1; }
+
+# Directory containing extracted APEX packages' payloads (ext4 images) under
+# the chroot directory.
+apex_image_dir="/tmp/apex"
+
+# deactivate_system_package APEX_NAME
+# -----------------------------------
+# Unmount APEX_NAME in `/apex` under the chroot directory and delete the
+# corresponding APEX package payload (ext4 image).
+deactivate_system_package() {
+  local apex_name=$1
+  local abs_image_filename="$ART_TEST_CHROOT$apex_image_dir/$apex_name.img"
+  local abs_mount_point="$ART_TEST_CHROOT/apex/$apex_name"
+
+  echo -e "${green}Deactivating package $apex_name${nc}"
+
+  # Unmount the package's payload (ext4 image).
+  if adb shell mount | grep -q "^/dev/block/loop[0-9]\+ on $abs_mount_point type ext4"; then
+    adb shell umount "$abs_mount_point"
+    adb shell rmdir "$abs_mount_point"
+    # Delete the ext4 image.
+    adb shell rm "$abs_image_filename"
+  fi
+}
+
+# Deactivate the Android Runtime APEX.
+deactivate_system_package com.android.runtime
+
+# Delete the image's directory.
+adb shell rmdir "$ART_TEST_CHROOT$apex_image_dir"