Merge "Improved error message when multiple annotations."
diff --git a/Android.mk b/Android.mk
index ba131c6..237dcd8 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:
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/apex/Android.bp b/build/apex/Android.bp
index 193a3c1..e810595 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",
@@ -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: {
@@ -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,7 +143,7 @@
                 + art_runtime_debug_binaries_prefer32,
         },
         first: {
-            binaries: art_tools_binaries,
+            binaries: art_tools_device_binaries,
         }
     },
     prebuilts: art_runtime_time_zone_prebuilts
@@ -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/compiler/debug/elf_debug_frame_writer.h b/compiler/debug/elf_debug_frame_writer.h
index e0116c6..27b70c8 100644
--- a/compiler/debug/elf_debug_frame_writer.h
+++ b/compiler/debug/elf_debug_frame_writer.h
@@ -182,7 +182,7 @@
   std::vector<const MethodDebugInfo*> sorted_method_infos;
   sorted_method_infos.reserve(method_infos.size());
   for (size_t i = 0; i < method_infos.size(); i++) {
-    if (!method_infos[i].deduped) {
+    if (!method_infos[i].cfi.empty() && !method_infos[i].deduped) {
       sorted_method_infos.push_back(&method_infos[i]);
     }
   }
@@ -222,6 +222,7 @@
     buffer.clear();
     for (const MethodDebugInfo* mi : sorted_method_infos) {
       DCHECK(!mi->deduped);
+      DCHECK(!mi->cfi.empty());
       const Elf_Addr code_address = mi->code_address +
           (mi->is_code_address_text_relative ? builder->GetText()->GetAddress() : 0);
       if (format == dwarf::DW_EH_FRAME_FORMAT) {
diff --git a/compiler/debug/elf_debug_writer.cc b/compiler/debug/elf_debug_writer.cc
index 16f163b..393db3d 100644
--- a/compiler/debug/elf_debug_writer.cc
+++ b/compiler/debug/elf_debug_writer.cc
@@ -226,7 +226,8 @@
           num_cfis++;
         });
     DCHECK_EQ(num_syms, 1u);
-    DCHECK_EQ(num_cfis, 1u);
+    // CFI might be missing. TODO: Ensure we have CFI for all methods.
+    DCHECK_LE(num_cfis, 1u);
   }
   return buffer;
 }
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/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index ea4158a..35af918 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -382,6 +382,9 @@
   UsageError("  --avoid-storing-invocation: Avoid storing the invocation args in the key value");
   UsageError("      store. Used to test determinism with different args.");
   UsageError("");
+  UsageError("  --write-invocation-to=<file>: Write the invocation commandline to the given file");
+  UsageError("      for later use. Used to test determinism with different host architectures.");
+  UsageError("");
   UsageError("  --runtime-arg <argument>: used to specify various arguments for the runtime,");
   UsageError("      such as initial heap size, maximum heap size, and verbose output.");
   UsageError("      Use a separate --runtime-arg switch for each argument.");
@@ -1001,6 +1004,21 @@
         CompilerFilter::NameOfFilter(compiler_options_->GetCompilerFilter()));
     key_value_store_->Put(OatHeader::kConcurrentCopying,
                           kUseReadBarrier ? OatHeader::kTrueValue : OatHeader::kFalseValue);
+    if (invocation_file_.get() != -1) {
+      std::ostringstream oss;
+      for (int i = 0; i < argc; ++i) {
+        if (i > 0) {
+          oss << std::endl;
+        }
+        oss << argv[i];
+      }
+      std::string invocation(oss.str());
+      if (TEMP_FAILURE_RETRY(write(invocation_file_.get(),
+                                   invocation.c_str(),
+                                   invocation.size())) == -1) {
+        Usage("Unable to write invocation file");
+      }
+    }
   }
 
   // This simple forward is here so the string specializations below don't look out of place.
@@ -1116,6 +1134,16 @@
 
     AssignTrueIfExists(args, M::Host, &is_host_);
     AssignTrueIfExists(args, M::AvoidStoringInvocation, &avoid_storing_invocation_);
+    if (args.Exists(M::InvocationFile)) {
+      invocation_file_.reset(open(args.Get(M::InvocationFile)->c_str(),
+                                  O_CREAT|O_WRONLY|O_TRUNC|O_CLOEXEC,
+                                  S_IRUSR|S_IWUSR));
+      if (invocation_file_.get() == -1) {
+        int err = errno;
+        Usage("Unable to open invocation file '%s' for writing due to %s.",
+              args.Get(M::InvocationFile)->c_str(), strerror(err));
+      }
+    }
     AssignIfExists(args, M::CopyDexFiles, &copy_dex_files_);
 
     if (args.Exists(M::ForceDeterminism)) {
@@ -2712,6 +2740,7 @@
   std::vector<std::unique_ptr<const DexFile>> opened_dex_files_;
 
   bool avoid_storing_invocation_;
+  android::base::unique_fd invocation_file_;
   std::string swap_file_name_;
   int swap_fd_;
   size_t min_dex_files_for_swap_ = kDefaultMinDexFilesForSwap;
diff --git a/dex2oat/dex2oat_options.cc b/dex2oat/dex2oat_options.cc
index 236c1fc..783b326 100644
--- a/dex2oat/dex2oat_options.cc
+++ b/dex2oat/dex2oat_options.cc
@@ -229,6 +229,9 @@
                          {"false", linker::CopyOption::kNever},
                          {"always", linker::CopyOption::kAlways}})
           .IntoKey(M::CopyDexFiles)
+      .Define("--write-invocation-to=_")
+          .WithType<std::string>()
+          .IntoKey(M::InvocationFile)
       .Define("--classpath-dir=_")
           .WithType<std::string>()
           .IntoKey(M::ClasspathDir)
diff --git a/dex2oat/dex2oat_options.def b/dex2oat/dex2oat_options.def
index c8cb7e7..0b77859 100644
--- a/dex2oat/dex2oat_options.def
+++ b/dex2oat/dex2oat_options.def
@@ -84,6 +84,7 @@
 DEX2OAT_OPTIONS_KEY (std::string,                    NoInlineFrom)
 DEX2OAT_OPTIONS_KEY (Unit,                           ForceDeterminism)
 DEX2OAT_OPTIONS_KEY (std::string,                    ClasspathDir)
+DEX2OAT_OPTIONS_KEY (std::string,                    InvocationFile)
 DEX2OAT_OPTIONS_KEY (std::string,                    ClassLoaderContext)
 DEX2OAT_OPTIONS_KEY (std::string,                    StoredClassLoaderContext)
 DEX2OAT_OPTIONS_KEY (std::string,                    DirtyImageObjects)
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/libartbase/Android.bp b/libartbase/Android.bp
index 0fcd6a5..109853c 100644
--- a/libartbase/Android.bp
+++ b/libartbase/Android.bp
@@ -64,6 +64,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 +83,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 +102,7 @@
                 // For common macros.
                 "libbase",
             ],
+            export_static_lib_headers: ["libbase"],
             cflags: ["-Wno-thread-safety"],
         },
     },
@@ -115,7 +121,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 {
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/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/openjdkjvm/OpenjdkJvm.cc b/openjdkjvm/OpenjdkJvm.cc
index 7a388c9..b2c4bb7 100644
--- a/openjdkjvm/OpenjdkJvm.cc
+++ b/openjdkjvm/OpenjdkJvm.cc
@@ -77,6 +77,7 @@
                    << fname << "')";
     }
 
+    flags |= O_CLOEXEC;
     int fd = TEMP_FAILURE_RETRY(open(fname, flags & ~JVM_O_DELETE, mode));
     if (fd < 0) {
         int err = errno;
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/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/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 aa09cbe..9949bf4 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -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
@@ -543,6 +548,10 @@
     return total_bytes_freed_ever_;
   }
 
+  space::RegionSpace* GetRegionSpace() const {
+    return region_space_;
+  }
+
   // Implements java.lang.Runtime.maxMemory, returning the maximum amount of memory a program can
   // consume. For a regular VM this would relate to the -Xmx option and would return -1 if no Xmx
   // were specified. Android apps start with a growth limit (small heap size) which is
@@ -1136,15 +1145,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/space/region_space-inl.h b/runtime/gc/space/region_space-inl.h
index 9f5c117..86a0a6e 100644
--- a/runtime/gc/space/region_space-inl.h
+++ b/runtime/gc/space/region_space-inl.h
@@ -249,27 +249,47 @@
     } else if (r->IsLargeTail()) {
       // Do nothing.
     } else {
-      // For newly allocated and evacuated regions, live bytes will be -1.
-      uint8_t* pos = r->Begin();
-      uint8_t* top = r->Top();
-      const bool need_bitmap =
-          r->LiveBytes() != static_cast<size_t>(-1) &&
-          r->LiveBytes() != static_cast<size_t>(top - pos);
-      if (need_bitmap) {
-        GetLiveBitmap()->VisitMarkedRange(
-            reinterpret_cast<uintptr_t>(pos),
-            reinterpret_cast<uintptr_t>(top),
-            visitor);
+      WalkNonLargeRegion(visitor, r);
+    }
+  }
+}
+
+template<typename Visitor>
+inline void RegionSpace::WalkNonLargeRegion(Visitor&& visitor, const Region* r) {
+  DCHECK(!r->IsLarge() && !r->IsLargeTail());
+  // For newly allocated and evacuated regions, live bytes will be -1.
+  uint8_t* pos = r->Begin();
+  uint8_t* top = r->Top();
+  // We need the region space bitmap to iterate over a region's objects
+  // if
+  // - its live bytes count is invalid (i.e. -1); or
+  // - its live bytes count is lower than the allocated bytes count.
+  //
+  // In both of the previous cases, we do not have the guarantee that
+  // all allocated objects are "alive" (i.e. valid), so we depend on
+  // the region space bitmap to identify which ones to visit.
+  //
+  // On the other hand, when all allocated bytes are known to be alive,
+  // we know that they form a range of consecutive objects (modulo
+  // object alignment constraints) that can be visited iteratively: we
+  // can compute the next object's location by using the current
+  // object's address and size (and object alignment constraints).
+  const bool need_bitmap =
+      r->LiveBytes() != static_cast<size_t>(-1) &&
+      r->LiveBytes() != static_cast<size_t>(top - pos);
+  if (need_bitmap) {
+    GetLiveBitmap()->VisitMarkedRange(
+        reinterpret_cast<uintptr_t>(pos),
+        reinterpret_cast<uintptr_t>(top),
+        visitor);
+  } else {
+    while (pos < top) {
+      mirror::Object* obj = reinterpret_cast<mirror::Object*>(pos);
+      if (obj->GetClass<kDefaultVerifyFlags, kWithoutReadBarrier>() != nullptr) {
+        visitor(obj);
+        pos = reinterpret_cast<uint8_t*>(GetNextObject(obj));
       } else {
-        while (pos < top) {
-          mirror::Object* obj = reinterpret_cast<mirror::Object*>(pos);
-          if (obj->GetClass<kDefaultVerifyFlags, kWithoutReadBarrier>() != nullptr) {
-            visitor(obj);
-            pos = reinterpret_cast<uint8_t*>(GetNextObject(obj));
-          } else {
-            break;
-          }
-        }
+        break;
       }
     }
   }
diff --git a/runtime/gc/space/region_space.cc b/runtime/gc/space/region_space.cc
index 07783ba..a5ba1dc 100644
--- a/runtime/gc/space/region_space.cc
+++ b/runtime/gc/space/region_space.cc
@@ -616,7 +616,7 @@
 
   // Functor poisoning the space between `obj` and the previously
   // visited (live) object (or the beginng of the region), if any.
-  auto maybe_poison = [this, &prev_obj_end](mirror::Object* obj) REQUIRES(Locks::mutator_lock_) {
+  auto maybe_poison = [&prev_obj_end](mirror::Object* obj) REQUIRES(Locks::mutator_lock_) {
     DCHECK_ALIGNED(obj, kAlignment);
     uint8_t* cur_obj_begin = reinterpret_cast<uint8_t*>(obj);
     if (cur_obj_begin != prev_obj_end) {
@@ -840,6 +840,9 @@
   if (live_bytes_ != static_cast<size_t>(-1)) {
     os << " ratio over allocated bytes="
        << (static_cast<float>(live_bytes_) / RoundUp(BytesAllocated(), kRegionSize));
+    uint64_t longest_consecutive_free_bytes = GetLongestConsecutiveFreeBytes();
+    os << " longest_consecutive_free_bytes=" << longest_consecutive_free_bytes
+       << " (" << PrettySize(longest_consecutive_free_bytes) << ")";
   }
 
   os << " is_newly_allocated=" << std::boolalpha << is_newly_allocated_ << std::noboolalpha
@@ -847,6 +850,30 @@
      << " thread=" << thread_ << '\n';
 }
 
+uint64_t RegionSpace::Region::GetLongestConsecutiveFreeBytes() const {
+  if (IsFree()) {
+    return kRegionSize;
+  }
+  if (IsLarge() || IsLargeTail()) {
+    return 0u;
+  }
+  uintptr_t max_gap = 0u;
+  uintptr_t prev_object_end = reinterpret_cast<uintptr_t>(Begin());
+  // Iterate through all live objects and find the largest free gap.
+  auto visitor = [&max_gap, &prev_object_end](mirror::Object* obj)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+    uintptr_t current = reinterpret_cast<uintptr_t>(obj);
+    uintptr_t diff = current - prev_object_end;
+    max_gap = std::max(diff, max_gap);
+    uintptr_t object_end = reinterpret_cast<uintptr_t>(obj) + obj->SizeOf();
+    prev_object_end = RoundUp(object_end, kAlignment);
+  };
+  space::RegionSpace* region_space = art::Runtime::Current()->GetHeap()->GetRegionSpace();
+  region_space->WalkNonLargeRegion(visitor, this);
+  return static_cast<uint64_t>(max_gap);
+}
+
+
 size_t RegionSpace::AllocationSizeNonvirtual(mirror::Object* obj, size_t* usable_size) {
   size_t num_bytes = obj->SizeOf();
   if (usable_size != nullptr) {
diff --git a/runtime/gc/space/region_space.h b/runtime/gc/space/region_space.h
index 75c99ec..a6f501b 100644
--- a/runtime/gc/space/region_space.h
+++ b/runtime/gc/space/region_space.h
@@ -370,9 +370,6 @@
  private:
   RegionSpace(const std::string& name, MemMap&& mem_map);
 
-  template<bool kToSpaceOnly, typename Visitor>
-  ALWAYS_INLINE void WalkInternal(Visitor&& visitor) NO_THREAD_SAFETY_ANALYSIS;
-
   class Region {
    public:
     Region()
@@ -616,6 +613,8 @@
       DCHECK_LE(Top(), end_);
     }
 
+    uint64_t GetLongestConsecutiveFreeBytes() const;
+
    private:
     size_t idx_;                        // The region's index in the region space.
     size_t live_bytes_;                 // The live bytes. Used to compute the live percent.
@@ -640,6 +639,14 @@
     friend class RegionSpace;
   };
 
+  template<bool kToSpaceOnly, typename Visitor>
+  ALWAYS_INLINE void WalkInternal(Visitor&& visitor) NO_THREAD_SAFETY_ANALYSIS;
+
+  // Visitor will be iterating on objects in increasing address order.
+  template<typename Visitor>
+  ALWAYS_INLINE void WalkNonLargeRegion(Visitor&& visitor, const Region* r)
+      NO_THREAD_SAFETY_ANALYSIS;
+
   Region* RefToRegion(mirror::Object* ref) REQUIRES(!region_lock_) {
     MutexLock mu(Thread::Current(), region_lock_);
     return RefToRegionLocked(ref);
@@ -674,7 +681,7 @@
   // - the region containing `obj` is fully used; and
   // - `obj` is not the last object of that region;
   // the returned location is not guaranteed to be a valid object.
-  mirror::Object* GetNextObject(mirror::Object* obj)
+  static mirror::Object* GetNextObject(mirror::Object* obj)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   void AdjustNonFreeRegionLimit(size_t new_non_free_region_index) REQUIRES(region_lock_) {
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/thread_list.cc b/runtime/thread_list.cc
index 75462ac..1b3b037 100644
--- a/runtime/thread_list.cc
+++ b/runtime/thread_list.cc
@@ -1476,24 +1476,26 @@
     // Remove and delete the Thread* while holding the thread_list_lock_ and
     // thread_suspend_count_lock_ so that the unregistering thread cannot be suspended.
     // Note: deliberately not using MutexLock that could hold a stale self pointer.
-    MutexLock mu(self, *Locks::thread_list_lock_);
-    if (!Contains(self)) {
-      std::string thread_name;
-      self->GetThreadName(thread_name);
-      std::ostringstream os;
-      DumpNativeStack(os, GetTid(), nullptr, "  native: ", nullptr);
-      LOG(ERROR) << "Request to unregister unattached thread " << thread_name << "\n" << os.str();
-      break;
-    } else {
-      MutexLock mu2(self, *Locks::thread_suspend_count_lock_);
-      if (!self->IsSuspended()) {
-        list_.remove(self);
+    {
+      MutexLock mu(self, *Locks::thread_list_lock_);
+      if (!Contains(self)) {
+        std::string thread_name;
+        self->GetThreadName(thread_name);
+        std::ostringstream os;
+        DumpNativeStack(os, GetTid(), nullptr, "  native: ", nullptr);
+        LOG(ERROR) << "Request to unregister unattached thread " << thread_name << "\n" << os.str();
         break;
+      } else {
+        MutexLock mu2(self, *Locks::thread_suspend_count_lock_);
+        if (!self->IsSuspended()) {
+          list_.remove(self);
+          break;
+        }
       }
-      // In the case where we are not suspended yet, sleep to leave other threads time to execute.
-      // This is important if there are realtime threads. b/111277984
-      usleep(1);
     }
+    // In the case where we are not suspended yet, sleep to leave other threads time to execute.
+    // This is important if there are realtime threads. b/111277984
+    usleep(1);
     // We failed to remove the thread due to a suspend request, loop and try again.
   }
   delete self;
diff --git a/tools/art b/tools/art
index eeb7c68..6e43863 100644
--- a/tools/art
+++ b/tools/art
@@ -222,6 +222,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 +236,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,7 +398,7 @@
 done
 
 PROG_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
-ANDROID_ROOT=$PROG_DIR/..
+ANDROID_ROOT="$(cd $PROG_DIR/..; pwd -P)"
 ANDROID_RUNTIME_ROOT=$ANDROID_ROOT/com.android.runtime
 ART_BINARY_PATH=$ANDROID_ROOT/bin/$ART_BINARY
 
@@ -439,6 +451,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/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